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