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