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