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