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