60b6067de3c015025205a8e0f8c733c52ec466a7
[occt.git] / src / AIS / AIS.cxx
1 // Created on: 1996-12-11
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1996-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
18 #include <Adaptor3d_HCurve.hxx>
19 #include <Adaptor3d_HSurface.hxx>
20 #include <AIS.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepAdaptor_HSurface.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <BRepBuilderAPI_MakeEdge.hxx>
27 #include <BRepBuilderAPI_MakeVertex.hxx>
28 #include <BRepTools.hxx>
29 #include <BRepTopAdaptor_FClass2d.hxx>
30 #include <ElCLib.hxx>
31 #include <ElSLib.hxx>
32 #include <GccEnt_QualifiedLin.hxx>
33 #include <gce_MakeDir.hxx>
34 #include <gce_MakeLin.hxx>
35 #include <Geom2d_Circle.hxx>
36 #include <Geom_CartesianPoint.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_ConicalSurface.hxx>
39 #include <Geom_Curve.hxx>
40 #include <Geom_CylindricalSurface.hxx>
41 #include <Geom_Ellipse.hxx>
42 #include <Geom_Line.hxx>
43 #include <Geom_OffsetSurface.hxx>
44 #include <Geom_Plane.hxx>
45 #include <Geom_SphericalSurface.hxx>
46 #include <Geom_Surface.hxx>
47 #include <Geom_SurfaceOfLinearExtrusion.hxx>
48 #include <Geom_SurfaceOfRevolution.hxx>
49 #include <Geom_ToroidalSurface.hxx>
50 #include <Geom_TrimmedCurve.hxx>
51 #include <GeomAPI_ExtremaCurveCurve.hxx>
52 #include <GeomAPI_IntSS.hxx>
53 #include <GeomAPI_ProjectPointOnCurve.hxx>
54 #include <GeomAPI_ProjectPointOnSurf.hxx>
55 #include <GeomLib.hxx>
56 #include <GeomProjLib.hxx>
57 #include <gp_Ax1.hxx>
58 #include <gp_Ax3.hxx>
59 #include <gp_Dir.hxx>
60 #include <gp_Elips.hxx>
61 #include <gp_Lin.hxx>
62 #include <gp_Pln.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Vec.hxx>
65 #include <gp_XYZ.hxx>
66 #include <Precision.hxx>
67 #include <Prs3d_LineAspect.hxx>
68 #include <Prs3d_PointAspect.hxx>
69 #include <Prs3d_Presentation.hxx>
70 #include <StdPrs_Point.hxx>
71 #include <StdPrs_WFShape.hxx>
72 #include <TColStd_Array1OfReal.hxx>
73 #include <TColStd_Array2OfReal.hxx>
74 #include <TopExp.hxx>
75 #include <TopExp_Explorer.hxx>
76 #include <TopoDS.hxx>
77 #include <TopoDS_Edge.hxx>
78 #include <TopoDS_Face.hxx>
79 #include <TopoDS_Shape.hxx>
80 #include <TopoDS_Vertex.hxx>
81 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
82
83 const Standard_Real SquareTolerance = Precision::SquareConfusion();
84
85 //=======================================================================
86 //function : Nearest
87 //purpose  :
88 //=======================================================================
89 gp_Pnt AIS::Nearest(const TopoDS_Shape& ashape, const gp_Pnt& apoint)
90 {
91   Standard_Real dist2 = RealLast();
92   Standard_Real curdist2;
93   gp_Pnt result(0.0,0.0,0.0);
94   gp_Pnt curpnt(0.0,0.0,0.0);
95   TopExp_Explorer explo(ashape,TopAbs_VERTEX);
96   while (explo.More())
97     {
98       curpnt = BRep_Tool::Pnt(TopoDS::Vertex(explo.Current()));
99       curdist2 = apoint.SquareDistance(curpnt);
100       if (curdist2 < dist2)
101         {
102           result = curpnt;
103           dist2 = curdist2;
104         }
105       explo.Next();
106     }
107   return result;
108 }
109
110 //=======================================================================
111 //function : Nearest
112 //purpose  : For <thePoint> finds the nearest point on <theLine>.
113 //=======================================================================
114 gp_Pnt AIS::Nearest (const gp_Lin& theLine, const gp_Pnt& thePoint)
115 {
116   Handle(Geom_Line) aLine = new Geom_Line (theLine);
117
118   GeomAPI_ProjectPointOnCurve aPointProj (thePoint, aLine);
119   return aPointProj.Point (1);
120 }
121
122 //=======================================================================
123 //function : Nearest
124 //purpose  : For the given point finds nearest point on the curve,
125 //           return TRUE if found point is belongs to curve
126 //              and FALSE otherwise.
127 //=======================================================================
128 Standard_Boolean AIS::Nearest (const Handle(Geom_Curve)& theCurve,
129                                const gp_Pnt& thePoint,
130                                const gp_Pnt& theFirstPoint,
131                                const gp_Pnt& theLastPoint,
132                                gp_Pnt& theNearestPoint)
133 {
134   GeomAPI_ProjectPointOnCurve aPointProj (thePoint, theCurve);
135   theNearestPoint = theCurve->Value (aPointProj.LowerDistanceParameter());
136
137   Standard_Real aLength = theFirstPoint.Distance (theLastPoint);
138
139   if (theNearestPoint.Distance (theFirstPoint) > aLength
140       || theNearestPoint.Distance (theLastPoint) >aLength)
141   {
142     return Standard_False;
143   }
144
145   return Standard_True;
146 }
147
148 //=======================================================================
149 //function : Farest
150 //purpose  :
151 //=======================================================================
152 gp_Pnt AIS::Farest( const TopoDS_Shape& aShape, const gp_Pnt& aPoint )
153 {
154   Standard_Real MaxDist2 = 0.0e0, curdist2;
155   gp_Pnt Result(0.0,0.0,0.0);
156   gp_Pnt curpnt(0.0,0.0,0.0);
157   TopExp_Explorer Explo( aShape, TopAbs_VERTEX );
158   for (; Explo.More(); Explo.Next())
159     {
160       curpnt = BRep_Tool::Pnt( TopoDS::Vertex( Explo.Current() ) );
161       curdist2 = aPoint.SquareDistance( curpnt );
162       if (curdist2 > MaxDist2)
163         {
164           MaxDist2 = curdist2;
165           Result = curpnt;
166         }
167     }
168   return Result;
169 }
170
171
172 //=======================================================================
173 //function : ComputeGeometry
174 //purpose  : for line, circle, ellipse.
175 //=======================================================================
176 Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge&  theEdge,
177                                        Handle(Geom_Curve)& theCurve,
178                                        gp_Pnt&             theFirstPnt,
179                                        gp_Pnt&             theLastPnt)
180 {
181   TopLoc_Location anEdgeLoc;
182   Standard_Real aFirst, aLast;
183   theCurve = BRep_Tool::Curve (theEdge, anEdgeLoc, aFirst, aLast);
184   if (theCurve.IsNull())
185   {
186     return Standard_False;
187   }
188
189   if (!anEdgeLoc.IsIdentity())
190   {
191     Handle(Geom_Geometry) aGeometry = theCurve->Transformed (anEdgeLoc.Transformation());
192     theCurve = Handle(Geom_Curve)::DownCast (aGeometry);
193   }
194
195   if (theCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
196   {
197     theCurve = Handle(Geom_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
198   }
199
200   if (theCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
201   {
202     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theCurve);
203     theFirstPnt = ElCLib::Value (aFirst, aLine->Lin());
204     theLastPnt = ElCLib::Value (aLast, aLine->Lin());
205   }
206   else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
207   {
208     Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theCurve);
209
210     theFirstPnt = ElCLib::Value (aFirst, aCirc->Circ());
211     theLastPnt = ElCLib::Value (aLast, aCirc->Circ());
212   }
213   else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Ellipse)))
214   {
215     Handle(Geom_Ellipse) anEllipse = Handle(Geom_Ellipse)::DownCast (theCurve);
216     theFirstPnt = ElCLib::Value (aFirst, anEllipse->Elips());
217     theLastPnt = ElCLib::Value (aLast, anEllipse->Elips());
218   }
219   else
220   {
221     return Standard_False;
222   }
223
224   return Standard_True;
225 }
226
227 //=======================================================================
228 //function : ComputeGeometry
229 //purpose  : for line, circle, ellipse.
230 //=======================================================================
231 Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theEdge,
232                                        Handle(Geom_Curve)& theCurve,
233                                        gp_Pnt& theFirstPnt,
234                                        gp_Pnt& theLastPnt,
235                                        Standard_Boolean& theIsInfinite)
236 {
237   Standard_Real aFirst, aLast;
238
239   BRepAdaptor_Curve anAdaptor (theEdge);
240
241   theCurve = Handle(Geom_Curve)::DownCast
242     (anAdaptor.Curve().Curve()->Transformed (anAdaptor.Trsf()));
243
244   if (theCurve.IsNull())
245   {
246     return Standard_False;
247   }
248
249   aFirst = anAdaptor.FirstParameter();
250   aLast = anAdaptor.LastParameter();
251
252   theIsInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
253
254   if (theCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
255   {
256     theCurve = Handle(Geom_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
257   }
258
259   if (!theIsInfinite)
260   {
261     theFirstPnt = theCurve->Value (aFirst);
262     theLastPnt  = theCurve->Value (aLast);
263   }
264   else
265   {
266     theFirstPnt = gp::Origin();
267     theLastPnt  = gp::Origin();
268   }
269
270   return Standard_True;
271 }
272
273 //=======================================================================
274 //function : ComputeGeometry
275 //purpose  :
276 //=======================================================================
277
278 Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theEdge,
279                                        Handle(Geom_Curve)& theCurve,
280                                        gp_Pnt& theFirstPnt,
281                                        gp_Pnt& theLastPnt,
282                                        Handle(Geom_Curve)& theExtCurve,
283                                        Standard_Boolean& theIsInfinite,
284                                        Standard_Boolean& theIsOnPlane,
285                                        const Handle(Geom_Plane)& thePlane)
286 {
287   if (thePlane.IsNull())
288   {
289     return Standard_False;
290   }
291
292   Standard_Real aFirst, aLast;
293   BRepAdaptor_Curve aCurveAdaptor (theEdge);
294   theCurve = Handle(Geom_Curve)::DownCast (aCurveAdaptor.Curve().Curve()->Transformed (aCurveAdaptor.Trsf()));
295   aFirst = aCurveAdaptor.FirstParameter();
296   aLast = aCurveAdaptor.LastParameter();
297
298   if (theCurve.IsNull())
299   {
300     return Standard_False;
301   }
302   
303   theExtCurve = theCurve;
304   theIsInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
305
306   // Checks that the projected curve is not in the plane.
307   theIsOnPlane = Standard_True;
308   if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
309   {
310     theExtCurve = Handle(Geom_TrimmedCurve)::DownCast (theExtCurve)->BasisCurve();
311   }
312
313   if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
314   {
315     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theExtCurve);
316     theIsOnPlane = thePlane->Pln().Contains (aLine->Lin(),
317                                              Precision::Confusion(),
318                                              Precision::Angular());
319   }
320   else if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
321   {
322     Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast (theExtCurve);
323
324     gp_Ax3 aCircPos (aCircle->Position());
325     theIsOnPlane = aCircPos.IsCoplanar (thePlane->Pln().Position(),
326                                                 Precision::Confusion(),
327                                                 Precision::Angular());
328   }
329
330   if (theIsOnPlane)
331   {
332     theExtCurve.Nullify();
333   }
334
335   theCurve = GeomProjLib::ProjectOnPlane (theCurve, thePlane,
336                                           thePlane->Pln().Axis().Direction(),
337                                           Standard_False);
338
339   if (theCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
340   {
341     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theCurve);
342     if (!theIsInfinite)
343     {
344       theFirstPnt = ElCLib::Value (aFirst, aLine->Lin());
345       theLastPnt = ElCLib::Value (aLast, aLine->Lin());
346     }
347   }
348   else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
349   {
350     Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theCurve);
351
352     theFirstPnt = ElCLib::Value (aFirst, aCirc->Circ());
353     theLastPnt = ElCLib::Value (aLast, aCirc->Circ());
354   }
355   else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Ellipse)))
356     {
357       Handle(Geom_Ellipse) anEllipse = Handle(Geom_Ellipse)::DownCast (theCurve);
358
359       theFirstPnt = ElCLib::Value (aFirst, anEllipse->Elips());
360       theLastPnt = ElCLib::Value (aLast, anEllipse->Elips());
361     }
362   else
363   {
364     return Standard_False;
365   }
366
367   return Standard_True;
368 }
369
370 //=======================================================================
371 //function : ComputeGeometry
372 //purpose  :
373 //=======================================================================
374 Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
375                                       const TopoDS_Edge& theSecondEdge,
376                                       Handle(Geom_Curve)& theFirstCurve,
377                                       Handle(Geom_Curve)& theSecondCurve,
378                                       gp_Pnt& theFirstPnt1,
379                                       gp_Pnt& theLastPnt1,
380                                       gp_Pnt& theFirstPnt2,
381                                       gp_Pnt& theLastPnt2,
382                                       const Handle(Geom_Plane)& thePlane)
383 {
384   if (thePlane.IsNull())
385   {
386     return Standard_False;
387   }
388
389   TopLoc_Location aFirstEdgeLoc, aSecondEdgeLoc;
390   Standard_Real aFirst1, aLast1, aFirst2, aLast2;
391   
392   theFirstCurve = BRep_Tool::Curve (theFirstEdge, aFirstEdgeLoc, aFirst1, aLast1);
393   theSecondCurve = BRep_Tool::Curve (theSecondEdge, aSecondEdgeLoc, aFirst2, aLast2);
394
395   if (theFirstCurve.IsNull())
396   {
397     return Standard_False;
398   }
399     
400   if (theSecondCurve.IsNull())
401   {
402     return Standard_False;
403   }
404   
405   if (!aFirstEdgeLoc.IsIdentity())
406   {
407     Handle(Geom_Geometry) aGeomGeometry = theFirstCurve->Transformed (aFirstEdgeLoc.Transformation());
408     theFirstCurve = Handle(Geom_Curve)::DownCast (aGeomGeometry);
409   }
410     
411   if (!aSecondEdgeLoc.IsIdentity())
412   {
413     Handle(Geom_Geometry) aGeomGeometry = theSecondCurve->Transformed (aSecondEdgeLoc.Transformation());
414     theSecondCurve = Handle(Geom_Curve)::DownCast (aGeomGeometry);
415   }
416
417   theFirstCurve = GeomProjLib::ProjectOnPlane (theFirstCurve, thePlane,
418                                                thePlane->Pln().Axis().Direction(),
419                                                Standard_False);
420
421
422   theSecondCurve = GeomProjLib::ProjectOnPlane (theSecondCurve, thePlane,
423                                                 thePlane->Pln().Axis().Direction(),
424                                                 Standard_False);
425
426
427   if (theFirstCurve->IsInstance (STANDARD_TYPE(Geom_TrimmedCurve)))
428   {
429     theFirstCurve = Handle(Geom_TrimmedCurve)::DownCast (theFirstCurve)->BasisCurve();
430   }
431     
432   if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
433   {
434     theSecondCurve = Handle(Geom_TrimmedCurve)::DownCast (theSecondCurve)->BasisCurve();
435   }
436
437   if (theFirstCurve->IsInstance(STANDARD_TYPE(Geom_Line)))
438   {
439     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theFirstCurve);
440
441     theFirstPnt1 = ElCLib::Value (aFirst1, aLine->Lin());
442     theLastPnt1 = ElCLib::Value (aLast1, aLine->Lin());
443   }
444   else if (theFirstCurve->IsInstance(STANDARD_TYPE(Geom_Circle)))
445   {
446     Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theFirstCurve);
447       
448     theFirstPnt1 = ElCLib::Value (aFirst1, aCirc->Circ());
449     theLastPnt1 = ElCLib::Value (aLast1, aCirc->Circ());
450   }
451   else
452   {
453     return Standard_False;
454   }
455
456   if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
457 {
458     Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theSecondCurve);
459
460     theFirstPnt2 = ElCLib::Value (aFirst2, aLine->Lin());
461     theLastPnt2 = ElCLib::Value (aLast2, aLine->Lin());
462   }
463   else if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
464   {
465     Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theSecondCurve);
466
467     theFirstPnt2 = ElCLib::Value (aFirst2, aCirc->Circ());
468     theLastPnt2 = ElCLib::Value (aLast2, aCirc->Circ());
469   }
470   else
471   {
472     return Standard_False;
473   }
474
475   return Standard_True;
476 }
477
478 //=======================================================================
479 //function : ComputeGeometry
480 //purpose  : Computes the geometry of the 2 edges.
481 //=======================================================================
482 Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
483                                        const TopoDS_Edge& theSecondEdge,
484                                        Handle(Geom_Curve)& theFirstCurve,
485                                        Handle(Geom_Curve)& theSecondCurve,
486                                        gp_Pnt& theFirstPnt1,
487                                        gp_Pnt& theLastPnt1,
488                                        gp_Pnt& theFirstPnt2,
489                                        gp_Pnt& theLastPnt2,
490                                        Standard_Boolean& theIsInfinite1,
491                                        Standard_Boolean& theIsInfinite2)
492 {
493     theIsInfinite1 = theIsInfinite2 = Standard_False;
494
495    if (!AIS::ComputeGeometry (theFirstEdge, theFirstCurve,theFirstPnt1, theLastPnt1, theIsInfinite1))
496    {
497      return Standard_False;
498    }
499
500    if (!AIS::ComputeGeometry (theSecondEdge, theSecondCurve,theFirstPnt2, theLastPnt2, theIsInfinite2))
501    {
502      return Standard_False;
503    }
504
505   if (theIsInfinite1 || theIsInfinite2)
506   {
507       if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType())
508       {
509           gp_Lin aLin1 = Handle(Geom_Line)::DownCast (theFirstCurve)->Lin();
510           gp_Lin aLin2 = Handle(Geom_Line)::DownCast (theSecondCurve)->Lin();
511
512           if (theIsInfinite1)
513           {
514               theFirstPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theFirstPnt2), aLin1);
515               theLastPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theLastPnt2), aLin1);
516           }
517           else if (theIsInfinite2)
518           {
519               theFirstPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theFirstPnt1), aLin2);
520               theLastPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theLastPnt1), aLin2);
521           }
522       }
523       else
524       {
525         if (theIsInfinite1 && !theIsInfinite2)
526         {
527           GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt2, theFirstCurve);
528           theFirstPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter ());
529
530           aProjector.Init (theLastPnt2, theFirstCurve);
531           theLastPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter ());
532         }
533         else if (!theIsInfinite1 && theIsInfinite2)
534         {
535           GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt1, theSecondCurve);
536           theFirstPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter ());
537
538           aProjector.Init (theLastPnt1, theSecondCurve);
539           theLastPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter ());
540         }
541         else
542         {
543           return Standard_False;
544         }
545       }
546   }
547
548     return Standard_True;
549 }
550
551 //=======================================================================
552 //function : ComputeGeometry
553 //purpose  : Computes the geometry of the 2 edges in the current wp
554 //           and the 'right' geometry of the edges if one doesn't
555 //           belong to the current working plane.
556 //           There may be only one curve that can't belong to the
557 //           current working plane ( attachement constraint)
558 //           if the 2 edges belong to the current WP, <WhatProj> = 0
559 //
560 //           indexExt = 0 2 edges are in the current wp
561 //           indexExt = 1 first edge is not in the current wp
562 //           indexExt = 2 second edge is not in the current wp
563 //           if none of the two edges is in the current wp ,
564 //           it returns Standard_False
565 //=======================================================================
566 Standard_Boolean AIS::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
567                                        const TopoDS_Edge& theSecondEdge,
568                                        Standard_Integer& theExtIndex,
569                                        Handle(Geom_Curve)& theFirstCurve,
570                                        Handle(Geom_Curve)& theSecondCurve,
571                                        gp_Pnt& theFirstPnt1,
572                                        gp_Pnt& theLastPnt1,
573                                        gp_Pnt& theFirstPnt2,
574                                        gp_Pnt& theLastPnt2,
575                                        Handle(Geom_Curve)& theExtCurve,
576                                        Standard_Boolean& theIsInfinite1,
577                                        Standard_Boolean& theIsInfinite2,
578                                        const Handle(Geom_Plane)& thePlane)
579 {
580   if (thePlane.IsNull())
581   {
582     return Standard_False;
583   }
584
585   theExtCurve.Nullify();
586   theExtIndex = 0;
587
588   Standard_Real aFirst1, aLast1, aFirst2, aLast2;
589   theIsInfinite1 = theIsInfinite2 = Standard_False;
590
591   BRepAdaptor_Curve aFirstAdaptor (theFirstEdge);
592   BRepAdaptor_Curve aSecondAdaptor (theSecondEdge);
593
594   theFirstCurve = Handle(Geom_Curve)::DownCast
595                   (aFirstAdaptor.Curve().Curve()->Transformed (aFirstAdaptor.Trsf()));
596   theSecondCurve = Handle(Geom_Curve)::DownCast
597                   (aSecondAdaptor.Curve().Curve()->Transformed (aSecondAdaptor.Trsf()));
598
599   if (theFirstCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
600   {
601     theFirstCurve = Handle(Geom_TrimmedCurve)::DownCast (theFirstCurve)->BasisCurve();
602   }
603   if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
604   {
605     theSecondCurve = Handle(Geom_TrimmedCurve)::DownCast (theSecondCurve)->BasisCurve();
606   }
607
608   aFirst1 = aFirstAdaptor.FirstParameter();
609   aLast1 = aFirstAdaptor.LastParameter();
610
611   aFirst2 = aSecondAdaptor.FirstParameter();
612   aLast2 = aSecondAdaptor.LastParameter();
613
614   if (theFirstCurve.IsNull() || theSecondCurve.IsNull())
615   {
616     return Standard_False;
617   }
618
619   Handle(Geom_Curve) aFirstSaved = theFirstCurve;
620   Handle(Geom_Curve) aSecondSaved = theSecondCurve;
621
622   // Checks that the projected curve is not in the plane
623   Standard_Boolean isFirstOnPlane,isSecondOnPlane;
624
625   if ((!ComputeGeomCurve (theFirstCurve, aFirst1, aLast1, theFirstPnt1, theLastPnt1, thePlane, isFirstOnPlane))
626       || (!ComputeGeomCurve( theSecondCurve, aFirst2, aLast2, theFirstPnt2, theLastPnt2, thePlane,isSecondOnPlane)))
627   {
628     return Standard_False;
629   }
630
631   if (Precision::IsInfinite (aFirst1) || Precision::IsInfinite (aLast1))
632   {
633     theIsInfinite1 = Standard_True;
634     theExtIndex = 1;
635   }
636   if (Precision::IsInfinite (aFirst2) || Precision::IsInfinite (aLast2))
637   {
638     theIsInfinite2 = Standard_True;
639     theExtIndex = 2;
640   }
641   if (theIsInfinite1 && theIsInfinite2)
642   {
643     theExtIndex = 0;
644   }
645
646   if (theIsInfinite1 || theIsInfinite2)
647   {
648     if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType())
649     {
650       gp_Lin aLin1 = Handle(Geom_Line)::DownCast (theFirstCurve)->Lin();
651       gp_Lin aLin2 = Handle(Geom_Line)::DownCast (theSecondCurve)->Lin();
652
653       if (theExtIndex == 1)
654       {
655         theFirstPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theFirstPnt2), aLin1);
656         theLastPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theLastPnt2), aLin1);
657       }
658       else if (theExtIndex == 2)
659       {
660         theFirstPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theFirstPnt1), aLin2);
661         theLastPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theLastPnt1), aLin2);
662       }
663     }
664   }
665
666   if (isFirstOnPlane && isSecondOnPlane)
667   {
668     return Standard_True;
669   }
670
671   if (!isFirstOnPlane && isSecondOnPlane)
672   {// curve 2 only in the plane
673     theExtIndex = 1;
674     theExtCurve = aFirstSaved;
675   }
676   else if (isFirstOnPlane && !isSecondOnPlane)
677   {// curve 1 only in the plane
678     theExtIndex = 2;
679     theExtCurve = aSecondSaved;
680   }
681   else
682   {
683     return Standard_False;
684   }
685
686   return Standard_True;
687 }
688
689 //=======================================================================
690 //function : ComputeGeomCurve
691 //purpose  : Checks if aCurve belongs to aPlane; if not, projects aCurve in aPlane
692 //           and returns aCurveproj;
693 //           Return TRUE if ok
694 //=======================================================================
695 Standard_Boolean AIS::ComputeGeomCurve (Handle(Geom_Curve)& aCurve,
696                                         const Standard_Real first1,
697                                         const Standard_Real last1,
698                                         gp_Pnt& FirstPnt1,
699                                         gp_Pnt& LastPnt1,
700                                         const Handle(Geom_Plane)& aPlane,
701                                         Standard_Boolean& isOnPlane)
702 {
703   isOnPlane = Standard_True;
704   const Standard_Integer NodeNumber = 20;
705   Standard_Real Delta = (last1 - first1) / (NodeNumber - 1);
706   if (Delta <= Precision::PConfusion())
707   {
708     Delta = last1 - first1;
709   }
710
711   gp_Pnt CurPnt(0.0, 0.0, 0.0);
712   Standard_Real CurPar = first1;
713   for (Standard_Integer i = 1; i <= NodeNumber; i++)
714   {
715     CurPnt = aCurve->Value( CurPar );
716     if (aPlane->Pln().SquareDistance( CurPnt ) > SquareTolerance)
717     {
718       isOnPlane = Standard_False;
719       break;
720     }
721     CurPar += Delta;
722   }
723
724   if (!Precision::IsInfinite(first1) && !Precision::IsInfinite(last1))
725   {
726     FirstPnt1 = aCurve->Value (first1);
727     LastPnt1  = aCurve->Value (last1);
728   }
729
730   if (!isOnPlane)
731   {
732     Handle(Geom_Curve) aGeomCurve = GeomProjLib::ProjectOnPlane (aCurve,
733                                                                 aPlane,
734                                                                 aPlane->Pln().Axis().Direction(),
735                                                                 Standard_False);
736     aCurve = aGeomCurve;
737     if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
738     {
739       aCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve)->BasisCurve();
740     }
741     if (! Precision::IsInfinite(first1) && ! Precision::IsInfinite(last1))
742     {
743       FirstPnt1 = AIS::ProjectPointOnPlane( FirstPnt1, aPlane->Pln() );
744       LastPnt1 = AIS::ProjectPointOnPlane( LastPnt1, aPlane->Pln() );
745     }
746   }
747   return Standard_True;
748 }
749
750 //=======================================================================
751 //function : ComputeGeometry
752 //purpose  : computes the point corresponding to the vertex <aVertex>
753 //           in the plane <aPlane>. If the vertex is already in the plane
754 //           <isOnPlane>, <isOnPlane> = true.
755 //           <point> is the projected vertex in the plane.
756 //=======================================================================
757 Standard_Boolean  AIS::ComputeGeometry(const TopoDS_Vertex& aVertex,
758                                        gp_Pnt& point,
759                                        const Handle(Geom_Plane)& aPlane,
760                                        Standard_Boolean& isOnPlane)
761 {
762   point = BRep_Tool::Pnt(aVertex);
763   isOnPlane = aPlane->Pln().Contains(point,  Precision::Confusion());
764   if ( !isOnPlane) {
765     point = AIS::ProjectPointOnPlane( point, aPlane->Pln() );
766   }
767   return Standard_True;
768 }
769
770 //=======================================================================
771 //function : GetPlaneFromFace
772 //purpose  :
773 //           Returns type of surface which can be Plane or OtherSurface
774 //=======================================================================
775 Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face&            aFace,
776                                         gp_Pln &                     aPlane,
777                                         Handle( Geom_Surface )&      aSurf,
778                                         AIS_KindOfSurface &          aSurfType,
779                                         Standard_Real &              Offset)
780
781 {
782   Standard_Boolean Result = Standard_False;
783   BRepAdaptor_Surface surf1( aFace );
784   Handle( Adaptor3d_HSurface ) surf2;
785   Standard_Boolean isOffset = Standard_False;
786
787   if (surf1.GetType() == GeomAbs_OffsetSurface)
788   {
789     // Extracting Basis Surface
790     surf2 = surf1.BasisSurface();
791     isOffset = Standard_True;
792   }
793   else
794     surf2 = new BRepAdaptor_HSurface( surf1 );
795
796   aSurf = surf1.Surface().Surface();
797   //  aSurf->Transform(surf1.Trsf()) ;
798   aSurf = Handle( Geom_Surface )::DownCast( aSurf->Transformed( surf1.Trsf() ) );
799
800   if (surf2->GetType() == GeomAbs_Plane)
801   {
802     aPlane = surf2->Plane();
803     aSurfType = AIS_KOS_Plane;
804     Offset = 0.;
805     Result = Standard_True;
806   }
807
808   else if (surf2->GetType() == GeomAbs_SurfaceOfExtrusion)
809   {
810     Handle( Adaptor3d_HCurve ) BasisCurve = surf2->BasisCurve();
811     gp_Dir ExtrusionDir = surf2->Direction();
812     if (BasisCurve->GetType() == GeomAbs_Line)
813     {
814       gp_Lin BasisLine = BasisCurve->Line();
815       gp_Dir LineDir = BasisLine.Direction();
816       gp_Pnt LinePos = BasisLine.Location();
817       gp_Pln thePlane( LinePos, LineDir ^ ExtrusionDir);
818       aPlane = thePlane;
819       aSurfType = AIS_KOS_Plane;
820       Offset = 0.;
821       Result = Standard_True;
822     }
823   }
824
825   if (Result == Standard_True && isOffset)
826   {
827     aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
828     aPlane = (Handle( Geom_Plane )::DownCast( aSurf ))->Pln();
829     Offset = 0.0e0;
830   }
831   if (Result == Standard_False)
832   {
833     if (isOffset)
834     {
835       Handle( Standard_Type ) TheType = aSurf->DynamicType();
836       if (TheType == STANDARD_TYPE(Geom_CylindricalSurface) ||
837         TheType == STANDARD_TYPE(Geom_ConicalSurface)     ||
838         TheType == STANDARD_TYPE(Geom_SphericalSurface)   ||
839         TheType == STANDARD_TYPE(Geom_ToroidalSurface))
840       {
841         aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
842         Offset = 0.0e0;
843       }
844       else
845       {
846         Offset = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Offset();
847         aSurf =  (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->BasisSurface();
848       }
849     }
850     Handle( Standard_Type ) TheType = aSurf->DynamicType();
851     if (TheType == STANDARD_TYPE(Geom_CylindricalSurface))
852       aSurfType = AIS_KOS_Cylinder;
853     else if (TheType == STANDARD_TYPE(Geom_ConicalSurface))
854       aSurfType = AIS_KOS_Cone;
855     else if (TheType == STANDARD_TYPE(Geom_SphericalSurface))
856       aSurfType = AIS_KOS_Sphere;
857     else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface))
858       aSurfType = AIS_KOS_Torus;
859     else if (TheType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
860       aSurfType = AIS_KOS_Revolution;
861     else if (TheType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
862       aSurfType = AIS_KOS_Extrusion;
863     else
864       aSurfType = AIS_KOS_OtherSurface;
865   }
866   return Result;
867 }
868
869
870 //=======================================================================
871 //function : ProjectPointOnPlane
872 //purpose  :
873 //=======================================================================
874
875 gp_Pnt AIS::ProjectPointOnPlane( const gp_Pnt & aPoint, const gp_Pln & aPlane )
876 {
877   gp_Vec aVec( aPlane.Location(), aPoint );
878   gp_Vec Normal = aPlane.Axis().Direction();
879   Normal = (aVec * Normal) * Normal;
880
881   return ( aPoint.Translated( -Normal ) );
882 }
883
884 //=======================================================================
885 //function : ProjectPointOnLine
886 //purpose  :
887 //=======================================================================
888
889 gp_Pnt AIS::ProjectPointOnLine( const gp_Pnt & aPoint, const gp_Lin & aLine )
890 {
891   gp_XYZ LinLoc = aLine.Location().XYZ();
892   gp_XYZ LinDir = aLine.Direction().XYZ();
893   Standard_Real Parameter = (aPoint.XYZ() - LinLoc) * LinDir;
894   gp_Pnt Result( LinLoc + Parameter * LinDir );
895   return Result;
896 }
897
898 //=======================================================================
899 //function : InitFaceLength
900 //purpose  : 
901 //=======================================================================
902 void AIS::InitFaceLength (const TopoDS_Face& aFace,
903                           gp_Pln               & aPlane,
904                           Handle(Geom_Surface) & aSurface,
905                           AIS_KindOfSurface    & aSurfaceType,
906                           Standard_Real        & anOffset)
907 {
908   AIS::GetPlaneFromFace( aFace, aPlane, aSurface, aSurfaceType, anOffset );
909   
910   if (Abs( anOffset ) > Precision::Confusion())
911     {
912       aSurface = new Geom_OffsetSurface( aSurface, anOffset );
913       anOffset = 0.0e0;
914     }
915   
916 }
917
918 //=======================================================================
919 //function : InitAngleBetweenPlanarFaces
920 //purpose  :
921 //=======================================================================
922 Standard_Boolean AIS::InitAngleBetweenPlanarFaces (const TopoDS_Face&          theFirstFace,
923                                                    const TopoDS_Face&          theSecondFace,
924                                                    gp_Pnt &                    theCenter,
925                                                    gp_Pnt &                    theFirstAttach,
926                                                    gp_Pnt &                    theSecondAttach,
927                                                    const Standard_Boolean      theIsFirstPointSet)
928 {
929   Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (BRep_Tool::Surface (theFirstFace));
930   Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (BRep_Tool::Surface (theSecondFace));
931
932   GeomAPI_IntSS aPlaneIntersector (aFirstPlane, aSecondPlane, Precision::Confusion());
933
934   // Fails if two planes haven't only one intersection line.
935   if (!aPlaneIntersector.IsDone())
936   {
937     return Standard_False;
938   }
939
940   if (aPlaneIntersector.NbLines() != 1)
941   {
942     return Standard_False;
943   }
944
945   // Get intersect line.
946   Handle(Geom_Curve) anIntersectCurve = aPlaneIntersector.Line (1);
947
948   Handle(Geom_Line) anIntersectLine = Handle(Geom_Line)::DownCast (anIntersectCurve);
949
950   if (anIntersectLine.IsNull())
951   {
952     return Standard_False;
953   }
954
955   gp_Lin anIntersectLin = anIntersectLine->Lin();
956
957   gp_Pnt aFirstCenter, aSecondCenter;
958   Standard_Real anU1Min, anU1Max, aV1Min, aV1Max;
959   Standard_Real anU2Min, anU2Max, aV2Min, aV2Max;
960
961   BRepTools::UVBounds (theFirstFace, anU1Min, anU1Max, aV1Min, aV1Max);
962   BRepTools::UVBounds (theSecondFace, anU2Min, anU2Max, aV2Min, aV2Max);
963
964   // Get first and second attach.
965   if (theIsFirstPointSet)
966   {
967     GeomAPI_ProjectPointOnSurf aProjector (theFirstAttach, aFirstPlane);
968     if (!aProjector.IsDone())
969     {
970       return Standard_False;
971     }
972
973     aFirstCenter = aProjector.Point (1);
974   }
975   else
976   {
977     aFirstCenter = aFirstPlane->Value ((anU1Min + anU1Max) * 0.5, (aV1Min + aV1Max) * 0.5);
978   }
979
980   aSecondCenter = aSecondPlane->Value ((anU2Min + anU2Max) * 0.5, (aV2Min + aV2Max) * 0.5);
981
982   GeomAPI_ProjectPointOnCurve aProj (aFirstCenter, anIntersectCurve);
983   theCenter = aProj.NearestPoint();
984
985   gp_Vec aFirstNormal = anIntersectLin.Direction() ^ aFirstPlane->Pln().Axis().Direction();
986   if (aFirstNormal * gp_Vec (theCenter, aFirstCenter) < 0.0)
987   {
988     aFirstNormal.Reverse();
989   }
990   theFirstAttach = theCenter.Translated (aFirstNormal);
991
992   gp_Vec aSecondNormal = anIntersectLin.Direction() ^ aSecondPlane->Pln().Axis().Direction();
993   if (aSecondNormal * gp_Vec (theCenter, aSecondCenter) < 0.0)
994   {
995     aSecondNormal.Reverse();
996   }
997   theSecondAttach = theCenter.Translated (aSecondNormal);
998
999   return Standard_True;
1000 }
1001
1002 //=======================================================================
1003 //function : InitAngleBetweenCurvilinearFaces
1004 //purpose  :
1005 //=======================================================================
1006 Standard_Boolean AIS::InitAngleBetweenCurvilinearFaces (const TopoDS_Face&          theFirstFace,
1007                                                         const TopoDS_Face&          theSecondFace,
1008                                                         const AIS_KindOfSurface     theFirstSurfType,
1009                                                         const AIS_KindOfSurface     theSecondSurfType,
1010                                                         gp_Pnt&                     theCenter,
1011                                                         gp_Pnt&                     theFirstAttach,
1012                                                         gp_Pnt&                     theSecondAttach,
1013                                                         const Standard_Boolean      theIsFirstPointSet)
1014 {
1015   Handle(Geom_Surface) aFirstSurf = BRep_Tool::Surface (theFirstFace);
1016   Handle(Geom_Surface) aSecondSurf = BRep_Tool::Surface (theSecondFace);
1017
1018   // Find intersection curve between two surfaces.
1019   GeomAPI_IntSS aSurfaceIntersector (aFirstSurf, aSecondSurf, Precision::Confusion());
1020
1021   // Fails if two planes haven't only one intersection line.
1022   if (!aSurfaceIntersector.IsDone())
1023   {
1024     return Standard_False;
1025   }
1026
1027   if (aSurfaceIntersector.NbLines() != 1)
1028   {
1029     return Standard_False;
1030   }
1031
1032   // Get intersect line.
1033   Handle(Geom_Curve) anIntersectCurve = aSurfaceIntersector.Line (1);
1034
1035   Handle(Geom_Line) aFirstLine, aSecondLine;
1036   Standard_Real aFirstU = 0.0;
1037   Standard_Real aFirstV = 0.0;
1038
1039   if (theIsFirstPointSet)
1040   {
1041     GeomAPI_ProjectPointOnSurf aProjector (theFirstAttach, aFirstSurf);
1042     if (!aProjector.IsDone())
1043     {
1044       return Standard_False;
1045     }
1046
1047     theFirstAttach = aProjector.Point (1);
1048   }
1049   else
1050   {
1051     theFirstAttach = aFirstSurf->Value (aFirstU, aFirstV);
1052   }
1053
1054   aFirstLine = Handle(Geom_Line)::DownCast (aFirstSurf->UIso (aFirstU));
1055
1056   if (theSecondSurfType == AIS_KOS_Cylinder)
1057   {
1058     Handle(Geom_CylindricalSurface) aCylinder = Handle(Geom_CylindricalSurface)::DownCast (aSecondSurf);
1059
1060     Standard_Real aSecondU = aCylinder->Cylinder().XAxis().Direction().Angle(
1061                                gce_MakeDir (ProjectPointOnLine (theFirstAttach,
1062                                                                 gp_Lin (aCylinder->Cylinder().Axis())),
1063                                             theFirstAttach));
1064
1065     aSecondLine = Handle(Geom_Line)::DownCast (aCylinder->UIso (aSecondU));
1066   }
1067   else if (theSecondSurfType == AIS_KOS_Cone)
1068   {
1069     Handle(Geom_ConicalSurface) aCone = Handle(Geom_ConicalSurface)::DownCast (aSecondSurf);
1070
1071     gp_Dir anXdirection = aCone->Cone().XAxis().Direction();
1072
1073     gp_Dir aToFirstAttach = gce_MakeDir (ProjectPointOnLine (theFirstAttach,
1074                                                              gp_Lin (aCone->Cone().Axis())),
1075                                          theFirstAttach);
1076
1077     Standard_Real aSecondU = anXdirection.Angle (aToFirstAttach);
1078
1079     // Check sign
1080     if (!anXdirection.IsEqual (aToFirstAttach, Precision::Angular()) &&
1081         !anXdirection.IsOpposite (aToFirstAttach, Precision::Angular()) &&
1082         (anXdirection ^ aToFirstAttach) * aCone->Cone().Axis().Direction() < 0.0)
1083     {
1084       aSecondU = 2*M_PI - aSecondU;
1085     }
1086     aSecondLine = Handle( Geom_Line )::DownCast (aCone->UIso(aSecondU));
1087   }
1088   else
1089   {
1090     return Standard_False;
1091   }
1092
1093   // If angle can be computed between two lines.
1094   if (!(aFirstLine->Lin().Direction().IsEqual (aSecondLine->Lin().Direction(), Precision::Angular() )) &&
1095       !(aFirstLine->Lin().Direction().IsOpposite (aSecondLine->Lin().Direction(), Precision::Angular())))
1096   {
1097     GeomAPI_ExtremaCurveCurve anIntersector (aFirstLine, aSecondLine);
1098     anIntersector.Points (1, theCenter, theCenter);
1099
1100     // Move theFirstAttach on aFirstLine if it is on theCenter.
1101     if (theCenter.SquareDistance(theFirstAttach ) <= SquareTolerance)
1102     {
1103       gp_Vec aDir (aFirstLine->Lin().Direction());
1104       theFirstAttach = theCenter.Translated (aDir);
1105
1106       // theFirstAttach should be on theFirstSurf.
1107       Standard_Real anU, aV;
1108       if (theFirstSurfType == AIS_KOS_Cylinder)
1109       {
1110         ElSLib::Parameters ((Handle(Geom_CylindricalSurface)::DownCast (aFirstSurf))->Cylinder(),
1111                             theFirstAttach, anU, aV);
1112
1113         theFirstAttach = ElSLib::Value (aFirstU, aV,
1114                                         (Handle( Geom_CylindricalSurface )::DownCast (aFirstSurf))->Cylinder() );
1115       }
1116       else if (theFirstSurfType == AIS_KOS_Cone)
1117       {
1118         ElSLib::Parameters ((Handle(Geom_ConicalSurface)::DownCast (aFirstSurf))->Cone(),
1119                              theFirstAttach, anU, aV);
1120         theFirstAttach = ElSLib::Value (aFirstU, aV,
1121                                        (Handle(Geom_ConicalSurface)::DownCast (aFirstSurf))->Cone());
1122       }
1123       else
1124       {
1125         return Standard_False;
1126       }
1127     }
1128
1129     // Find theSecondAttach
1130     GeomAPI_ProjectPointOnSurf aProjector (theFirstAttach, aSecondSurf);
1131     if (!aProjector.IsDone())
1132     {
1133       return Standard_False;
1134     }
1135     Standard_Real anU, aV;
1136     aProjector.LowerDistanceParameters (anU, aV);
1137     theSecondAttach = aSecondSurf->Value (anU, aV);
1138   }
1139   else // aFirstLine and aSecondLine are coincident
1140   {
1141       gp_Vec aDir (aFirstLine->Lin().Direction());
1142       theFirstAttach = theCenter.Translated (aDir);
1143       theSecondAttach = theCenter.Translated (-aDir);
1144   }
1145   return Standard_True;
1146 }
1147
1148 //=======================================================================
1149 //function : ComputeLengthBetweenCurvilinearFaces
1150 //purpose  : 
1151 //=======================================================================
1152 void AIS::InitLengthBetweenCurvilinearFaces (const TopoDS_Face&    theFirstFace,
1153                                              const TopoDS_Face&    theSecondFace,
1154                                              Handle(Geom_Surface)& theFirstSurf,
1155                                              Handle(Geom_Surface)& theSecondSurf,
1156                                              gp_Pnt&               theFirstAttach,
1157                                              gp_Pnt&               theSecondAttach,
1158                                              gp_Dir&               theDirOnPlane)
1159 {
1160   GeomAPI_ProjectPointOnSurf aProjector;
1161   Standard_Real aPU, aPV;
1162
1163   TopExp_Explorer anExplorer (theFirstFace, TopAbs_VERTEX);
1164
1165   theFirstAttach = BRep_Tool::Pnt (TopoDS::Vertex (anExplorer.Current()));
1166   aProjector.Init (theFirstAttach, theFirstSurf);
1167
1168   theFirstAttach = aProjector.NearestPoint();
1169   aProjector.LowerDistanceParameters (aPU, aPV);
1170
1171   gp_Vec aD1U, aD1V;
1172   theFirstSurf->D1 (aPU, aPV, theFirstAttach, aD1U, aD1V);
1173
1174   if (aD1U.SquareMagnitude() <= SquareTolerance || aD1V.SquareMagnitude() <= SquareTolerance)
1175   {
1176     theFirstAttach = AIS::Farest (theFirstFace, theFirstAttach);
1177     aProjector.Init (theFirstAttach, theFirstSurf);
1178     aProjector.LowerDistanceParameters (aPU, aPV);
1179     theFirstSurf->D1 (aPU, aPV, theFirstAttach, aD1U, aD1V);
1180   }
1181
1182   aD1U.Normalize();
1183   aD1V.Normalize();
1184
1185   theDirOnPlane = gp_Dir (aD1U);
1186
1187   gp_Dir aFirstSurfN = gp_Dir (aD1U ^ aD1V);
1188
1189   aProjector.Init (theFirstAttach, theSecondSurf);
1190
1191   Standard_Integer aBestPointIndex = 0;
1192   Standard_Real aMinDist = RealLast();
1193   gp_Dir aLocalDir;
1194
1195   for (Standard_Integer aPointIt = 1; aPointIt <= aProjector.NbPoints(); aPointIt++)
1196   {
1197     aProjector.Parameters (aPointIt, aPU, aPV);
1198
1199     theSecondSurf->D1 (aPU, aPV, theSecondAttach, aD1U, aD1V);
1200
1201     aLocalDir = aD1U.SquareMagnitude() <= SquareTolerance || aD1V.SquareMagnitude() <= SquareTolerance
1202               ? gp_Dir (gp_Vec (theFirstAttach, aProjector.Point (aPointIt)))
1203               : gp_Dir (aD1U ^ aD1V);
1204
1205     if (aFirstSurfN.IsParallel (aLocalDir, Precision::Angular()) && aProjector.Distance (aPointIt) < aMinDist)
1206     {
1207       aBestPointIndex = aPointIt;
1208       aMinDist = aProjector.Distance (aPointIt);
1209     }
1210   }
1211
1212   if (aBestPointIndex == 0)
1213   {
1214     theSecondAttach = theFirstAttach;
1215   }
1216   else
1217   {
1218     theSecondAttach = aProjector.Point (aBestPointIndex);
1219     aProjector.Parameters (aBestPointIndex, aPU, aPV);
1220
1221     // Now there is projection of FirstAttach onto SecondSurf in aProjector
1222     BRepTopAdaptor_FClass2d aClassifier (theSecondFace, Precision::Confusion());
1223
1224     TopAbs_State aState = 
1225       aClassifier.Perform (gp_Pnt2d (aPU, aPV), theSecondSurf->IsUPeriodic() || theSecondSurf->IsVPeriodic());
1226
1227     if (aState == TopAbs_OUT || aState == TopAbs_UNKNOWN)
1228     {
1229       theSecondAttach = AIS::Nearest (theSecondFace, theSecondAttach);
1230     }
1231   }
1232 }
1233
1234 gp_Pnt AIS::TranslatePointToBound( const gp_Pnt & aPoint, const gp_Dir & aDir, const Bnd_Box & aBndBox )
1235 {
1236   if (aBndBox.IsOut( aPoint ))
1237     return aPoint;
1238   else
1239     {
1240       gp_Pnt Result(0.0,0.0,0.0);
1241       TColStd_Array2OfReal Bound( 1, 3, 1, 2 );
1242       TColStd_Array1OfReal Origin( 1, 3 );
1243       TColStd_Array1OfReal Dir( 1, 3 );
1244       Standard_Real t;
1245       
1246       aBndBox.Get( Bound(1,1), Bound(2,1), Bound(3,1), Bound(1,2),  Bound(2,2), Bound(3,2) );
1247       aPoint.Coord( Origin(1), Origin(2), Origin(3) );
1248       aDir.Coord( Dir(1), Dir(2), Dir(3) );
1249
1250       Bnd_Box EnlargedBox = aBndBox;
1251       EnlargedBox.Enlarge( aBndBox.GetGap() + Precision::Confusion() );
1252
1253       Standard_Boolean IsFound = Standard_False;
1254       for (Standard_Integer i = 1; i <= 3; i++)
1255         {
1256           if (Abs( Dir( i ) ) <= gp::Resolution())
1257             continue;
1258           for (Standard_Integer j = 1; j <= 2; j++)
1259             {
1260               t = (Bound( i, j ) - Origin( i )) / Dir( i );
1261               if (t < 0.0e0)
1262                 continue;
1263               Result = aPoint.Translated( gp_Vec( aDir ) * t );
1264               if (! EnlargedBox.IsOut( Result ))
1265                 {
1266                   IsFound = Standard_True;
1267                   break;
1268                 }
1269             }
1270           if (IsFound) break;
1271         }
1272       return Result;
1273     }
1274 }
1275
1276
1277 //=======================================================================
1278 //function : InDomain
1279 //purpose  : 
1280 //=======================================================================
1281
1282 Standard_Boolean AIS::InDomain(const Standard_Real fpar,
1283                                const Standard_Real lpar,
1284                                const Standard_Real para) 
1285 {
1286   if (fpar >= 0.) {
1287     if(lpar > fpar)
1288       return ((para >= fpar) && (para <= lpar));
1289     else { // fpar > lpar
1290       Standard_Real delta = 2*M_PI-fpar;
1291       Standard_Real lp, par, fp;
1292       lp = lpar + delta;
1293       par = para + delta;
1294       while(lp > 2*M_PI) lp-=2*M_PI;
1295       while(par > 2*M_PI) par-=2*M_PI;
1296       fp = 0.;
1297       return ((par >= fp) && (par <= lp));
1298     }
1299       
1300   }
1301   if (para >= (fpar+2*M_PI)) return Standard_True;
1302   if (para <= lpar) return Standard_True;
1303   return Standard_False;
1304 }
1305
1306 //=======================================================================
1307 //function : DistanceFromApex
1308 //purpose  : calculates parametric length arc of ellipse
1309 //=======================================================================
1310
1311 Standard_Real AIS::DistanceFromApex(const gp_Elips & elips,
1312                                     const gp_Pnt   & Apex,
1313                                     const Standard_Real par)
1314 {
1315   Standard_Real dist;
1316   Standard_Real parApex = ElCLib::Parameter ( elips, Apex );
1317   if(parApex == 0.0 || parApex == M_PI) 
1318     {//Major case
1319       if(parApex == 0.0) //pos Apex
1320         dist = (par < M_PI) ? par : (2*M_PI - par);
1321       else //neg Apex
1322         dist = (par < M_PI) ? ( M_PI - par) : ( par - M_PI );
1323     }
1324   else 
1325     {// Minor case
1326       if(parApex == M_PI / 2) //pos Apex
1327         {
1328           if(par <= parApex + M_PI && par > parApex) // 3/2*M_PI < par < M_PI/2
1329             dist = par - parApex;
1330           else 
1331             { 
1332               if(par >  parApex + M_PI) // 3/2*M_PI < par < 2*M_PI
1333                 dist = 2*M_PI - par + parApex;
1334               else
1335                 dist = parApex - par; 
1336             }
1337           }
1338       else //neg Apex == 3/2*M_PI
1339         {
1340           if(par <= parApex && par >= M_PI/2) // M_PI/2 < par < 3/2*M_PI
1341             dist = parApex - par;
1342           else
1343             {
1344               if(par >  parApex) // 3/2*M_PI < par < 2*M_PI
1345                 dist = par - parApex;
1346               else
1347                 dist = par + M_PI/2; // 0 < par < M_PI/2
1348             }
1349         }
1350     }
1351   return dist;
1352 }
1353
1354 //=======================================================================
1355 //function : NearestApex
1356 //purpose  : 
1357 //=======================================================================
1358
1359 gp_Pnt AIS::NearestApex(const gp_Elips & elips,
1360                         const gp_Pnt   & pApex,
1361                         const gp_Pnt   & nApex,
1362                         const Standard_Real fpara,
1363                         const Standard_Real lpara,
1364                               Standard_Boolean & IsInDomain)
1365 {
1366   Standard_Real parP, parN;
1367   gp_Pnt EndOfArrow(0.0,0.0,0.0);
1368   IsInDomain = Standard_True;
1369   parP = ElCLib::Parameter ( elips, pApex );
1370   if(InDomain(fpara, lpara, parP)) EndOfArrow = pApex;
1371   else 
1372     {
1373       parN = ElCLib::Parameter ( elips, nApex );
1374       if(InDomain(fpara, lpara, parN)) EndOfArrow = nApex;
1375       else {
1376         IsInDomain = Standard_False;
1377         Standard_Real posd = Min(DistanceFromApex (elips,pApex, fpara), 
1378                                  DistanceFromApex (elips,pApex, lpara));
1379         Standard_Real negd = Min(DistanceFromApex (elips,nApex, fpara), 
1380                                  DistanceFromApex (elips,nApex, lpara));
1381         if( posd < negd ) 
1382           EndOfArrow = pApex;
1383         else
1384           EndOfArrow = nApex;
1385       }
1386     }
1387   return EndOfArrow;
1388 }
1389
1390 //=======================================================================
1391 //function : ComputeProjEdgePresentation
1392 //purpose  : 
1393 //=======================================================================
1394
1395 void AIS::ComputeProjEdgePresentation (const Handle(Prs3d_Presentation)& aPresentation,
1396                                        const Handle(Prs3d_Drawer)& aDrawer,
1397                                        const TopoDS_Edge& anEdge,
1398                                        const Handle(Geom_Curve)& ProjCurve,
1399                                        const gp_Pnt& FirstP,
1400                                        const gp_Pnt& LastP,
1401                                        const Quantity_NameOfColor aColor,
1402                                        const Standard_Real aWidth,
1403                                        const Aspect_TypeOfLine aProjTOL,
1404                                        const Aspect_TypeOfLine aCallTOL)
1405 {
1406   if (!aDrawer->HasOwnWireAspect()){
1407     aDrawer->SetWireAspect(new Prs3d_LineAspect(aColor,aProjTOL,2.));}
1408   else {
1409     // CLE
1410     // const Handle(Prs3d_LineAspect)& li = aDrawer->WireAspect();
1411     Handle(Prs3d_LineAspect) li = aDrawer->WireAspect();
1412     // ENDCLE
1413     li->SetColor(aColor);
1414     li->SetTypeOfLine(aProjTOL);
1415     li->SetWidth(aWidth);
1416   }
1417
1418   Standard_Real pf, pl;
1419   TopLoc_Location loc;
1420   Handle(Geom_Curve) curve;
1421   Standard_Boolean isInfinite;
1422   curve = BRep_Tool::Curve(anEdge,loc,pf,pl);
1423   isInfinite = (Precision::IsInfinite(pf) || Precision::IsInfinite(pl));
1424
1425   TopoDS_Edge E;
1426
1427   // Calculate  presentation of the edge
1428   if (ProjCurve->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1429     // CLE
1430     // Handle(Geom_Line) gl (Handle(Geom_Line)::DownCast (ProjCurve));
1431     Handle(Geom_Line) gl = Handle(Geom_Line)::DownCast (ProjCurve);
1432     // ENDCLE
1433     if ( !isInfinite) {
1434       pf = ElCLib::Parameter(gl->Lin(),FirstP);
1435       pl = ElCLib::Parameter(gl->Lin(),LastP);
1436       BRepBuilderAPI_MakeEdge MakEd(gl->Lin(), pf, pl);
1437       E = MakEd.Edge();
1438     }
1439     else {
1440       BRepBuilderAPI_MakeEdge MakEd(gl->Lin());
1441       E = MakEd.Edge();
1442     }
1443   }
1444   else if (ProjCurve->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1445     // CLE
1446     // Handle(Geom_Circle) gc (Handle(Geom_Circle)::DownCast (ProjCurve));
1447     Handle(Geom_Circle) gc = Handle(Geom_Circle)::DownCast (ProjCurve);
1448     // ENDCLE
1449     pf = ElCLib::Parameter(gc->Circ(),FirstP);
1450     pl = ElCLib::Parameter(gc->Circ(),LastP);
1451     BRepBuilderAPI_MakeEdge MakEd(gc->Circ(),pf, pl);
1452     E = MakEd.Edge();
1453   }
1454   StdPrs_WFShape::Add (aPresentation, E, aDrawer);
1455
1456   //Calculate the presentation of line connections
1457   aDrawer->WireAspect()->SetTypeOfLine(aCallTOL);
1458   if (!isInfinite) {
1459     gp_Pnt ppf(0.0,0.0,0.0), ppl(0.0,0.0,0.0);
1460     ppf = BRep_Tool::Pnt( TopExp::FirstVertex(TopoDS::Edge(anEdge)));
1461     ppl = BRep_Tool::Pnt( TopExp::LastVertex(TopoDS::Edge(anEdge)));
1462
1463     // it is patch!
1464     if (FirstP.SquareDistance (ppf) > SquareTolerance)
1465     {
1466       BRepBuilderAPI_MakeEdge MakEd1 (FirstP, ppf);
1467       StdPrs_WFShape::Add (aPresentation, MakEd1.Edge(), aDrawer);
1468     }
1469     else
1470     {
1471       BRepBuilderAPI_MakeVertex MakVert1 (FirstP);
1472       StdPrs_WFShape::Add (aPresentation, MakVert1.Vertex(), aDrawer);
1473     }
1474     if (LastP.SquareDistance (ppl) > SquareTolerance)
1475     {
1476       BRepBuilderAPI_MakeEdge MakEd2 (LastP, ppl);
1477       StdPrs_WFShape::Add (aPresentation, MakEd2.Edge(), aDrawer);
1478     }
1479     else
1480     {
1481       BRepBuilderAPI_MakeVertex MakVert2 (LastP);
1482       StdPrs_WFShape::Add (aPresentation, MakVert2.Vertex(), aDrawer);
1483     }
1484 /*
1485     BRepBuilderAPI_MakeEdge MakEd1 (FirstP, ppf);
1486     StdPrs_WFShape::Add (aPresentation, MakEd1.Edge(), aDrawer);
1487     BRepBuilderAPI_MakeEdge MakEd2 (LastP, ppl);
1488     StdPrs_WFShape::Add (aPresentation, MakEd2.Edge(), aDrawer);
1489 */
1490   }
1491 }
1492
1493 //=======================================================================
1494 //function : ComputeProjVertexPresentation
1495 //purpose  : 
1496 //=======================================================================
1497
1498 void AIS::ComputeProjVertexPresentation (const Handle( Prs3d_Presentation )& aPresentation,
1499                                          const Handle( Prs3d_Drawer )& aDrawer,
1500                                          const TopoDS_Vertex& aVertex,
1501                                          const gp_Pnt& ProjPoint,
1502                                          const Quantity_NameOfColor aColor,
1503                                          const Standard_Real aWidth,
1504                                          const Aspect_TypeOfMarker aProjTOM,
1505                                          const Aspect_TypeOfLine aCallTOL)
1506 {
1507   if (!aDrawer->HasOwnPointAspect()){
1508     aDrawer->SetPointAspect(new Prs3d_PointAspect(aProjTOM, aColor,1));}
1509   else {
1510     // CLE
1511     // const Handle(Prs3d_PointAspect)& pa = aDrawer->PointAspect();
1512     Handle(Prs3d_PointAspect) pa = aDrawer->PointAspect();
1513     // ENDCLE
1514     pa->SetColor(aColor);
1515     pa->SetTypeOfMarker(aProjTOM);
1516   }
1517   
1518   // calculate the projection
1519   StdPrs_Point::Add(aPresentation, new Geom_CartesianPoint(ProjPoint), aDrawer);
1520
1521   if (!aDrawer->HasOwnWireAspect()){
1522     aDrawer->SetWireAspect(new Prs3d_LineAspect(aColor,aCallTOL,2.));}
1523   else {
1524     // CLE
1525     // const Handle(Prs3d_LineAspect)& li = aDrawer->WireAspect();
1526     Handle(Prs3d_LineAspect) li = aDrawer->WireAspect();
1527     // ENDCLE
1528     li->SetColor(aColor);
1529     li->SetTypeOfLine(aCallTOL);
1530     li->SetWidth(aWidth);
1531   }
1532   
1533   // If the points are not mixed...
1534   if (!ProjPoint.IsEqual (BRep_Tool::Pnt (aVertex), Precision::Confusion()))
1535   {
1536     // calculate the lines of recall
1537     BRepBuilderAPI_MakeEdge MakEd (ProjPoint, BRep_Tool::Pnt (aVertex));
1538     StdPrs_WFShape::Add (aPresentation, MakEd.Edge(), aDrawer);
1539   }
1540 }