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