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