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