0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / AIS / AIS_TangentRelation.cxx
CommitLineData
b311480e 1// Created on: 1996-12-05
2// Created by: Jean-Pierre COMBE/Odile Olivier
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
7fd59977 17
42cf5bc1 18#include <AIS.hxx>
19#include <AIS_Shape.hxx>
20#include <AIS_TangentRelation.hxx>
21#include <Bnd_Box.hxx>
7fd59977 22#include <BRep_Tool.hxx>
7fd59977 23#include <BRepAdaptor_Surface.hxx>
24#include <BRepBuilderAPI_MakeFace.hxx>
42cf5bc1 25#include <DsgPrs_TangentPresentation.hxx>
7fd59977 26#include <ElCLib.hxx>
42cf5bc1 27#include <Geom_Circle.hxx>
28#include <Geom_Ellipse.hxx>
29#include <Geom_Line.hxx>
30#include <Geom_Plane.hxx>
31#include <Geom_Transformation.hxx>
32#include <GeomAPI_ExtremaCurveCurve.hxx>
7fd59977 33#include <gp_Circ.hxx>
42cf5bc1 34#include <gp_Lin.hxx>
35#include <gp_Pln.hxx>
7fd59977 36#include <gp_Pnt.hxx>
37#include <gp_Vec.hxx>
7fd59977 38#include <Precision.hxx>
42cf5bc1 39#include <Prs3d_Presentation.hxx>
40#include <Prs3d_Projector.hxx>
41#include <Select3D_SensitiveSegment.hxx>
42#include <SelectMgr_EntityOwner.hxx>
43#include <SelectMgr_Selection.hxx>
44#include <Standard_NotImplemented.hxx>
45#include <Standard_Type.hxx>
46#include <TColStd_ListIteratorOfListOfTransient.hxx>
47#include <TopAbs_ShapeEnum.hxx>
48#include <TopExp_Explorer.hxx>
49#include <TopoDS.hxx>
50#include <TopoDS_Edge.hxx>
51#include <TopoDS_Face.hxx>
52#include <TopoDS_Shape.hxx>
53#include <TopoDS_Vertex.hxx>
7fd59977 54
55//=======================================================================
56//function : Constructor
57//purpose :
58//=======================================================================
59AIS_TangentRelation::AIS_TangentRelation(const TopoDS_Shape& aFShape,
60 const TopoDS_Shape& aSShape,
61 const Handle(Geom_Plane)& aPlane,
62 const Standard_Integer anExternRef)
63 :myExternRef(anExternRef)
64{
65 myFShape = aFShape;
66 mySShape = aSShape;
67 myPlane = aPlane;
68 myAutomaticPosition = Standard_False;
69}
70
71//=======================================================================
72//function : ExternRef
73//purpose :
74//=======================================================================
75Standard_Integer AIS_TangentRelation::ExternRef()
76{
77 return myExternRef;
78}
79
80//=======================================================================
81//function : SetExternRef
82//purpose :
83//=======================================================================
84void AIS_TangentRelation::SetExternRef(const Standard_Integer aRef)
85{
86 myExternRef = aRef;
87}
88
89//=======================================================================
90//function : Compute
91//purpose :
92//=======================================================================
93void AIS_TangentRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
94 const Handle(Prs3d_Presentation)& aPresentation,
95 const Standard_Integer)
96{
97 aPresentation->Clear();
98
99 switch (myFShape.ShapeType())
100 {
101 case TopAbs_FACE :
102 {
103 ComputeTwoFacesTangent(aPresentation);
104 }
105 break;
106 case TopAbs_EDGE :
107 {
108 ComputeTwoEdgesTangent(aPresentation);
109 }
110 break;
111 default:
112 break;
113 }
114}
115
116//=======================================================================
117//function : Compute
118//purpose : to avoid warning
119//=======================================================================
120void AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
121 const Handle(Prs3d_Presentation)& aPresentation)
122{
123// Standard_NotImplemented::Raise("AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
124 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
125}
126
857ffd5e 127void AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
128 const Handle(Geom_Transformation)& aTransformation,
129 const Handle(Prs3d_Presentation)& aPresentation)
7fd59977 130{
857ffd5e 131// Standard_NotImplemented::Raise("AIS_TangentRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
7fd59977 132 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
133}
134
135//=======================================================================
136//function : ComputeSelection
137//purpose :
138//=======================================================================
139void AIS_TangentRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
140 const Standard_Integer)
141{
142 gp_Vec vec(myDir);
143 gp_Vec vec1 = vec.Multiplied(myLength);
144 gp_Vec vec2 = vec.Multiplied(-myLength);
145 gp_Pnt p1 = myPosition.Translated(vec1);
146 gp_Pnt p2 = myPosition.Translated(vec2);
147
148 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
149 Handle(Select3D_SensitiveSegment) seg = new Select3D_SensitiveSegment(own,p1,p2);
150 aSelection->Add(seg);
151}
152
153//=======================================================================
154//function : ComputeTwoFacesTangent
155//purpose :
156//=======================================================================
157void AIS_TangentRelation::ComputeTwoFacesTangent
158 (const Handle(Prs3d_Presentation)& /*aPresentation*/)
159{
160}
161
162// jfa 19/10/2000 begin
163//=======================================================================
164//function : ComputeTangencyPoint
165//purpose :
166//=======================================================================
167static Standard_Boolean ComputeTangencyPoint(const Handle(Geom_Curve)& GC1,
168 const Handle(Geom_Curve)& GC2,
169 gp_Pnt& aPoint)
170{
171 Standard_Real U1f = GC1->FirstParameter();
172 Standard_Real U1l = GC1->LastParameter();
173 Standard_Real U2f = GC2->FirstParameter();
174 Standard_Real U2l = GC2->LastParameter();
175
176 gp_Pnt PC1;
177 Standard_Real mindist=0;
178 GeomAPI_ExtremaCurveCurve Ex(GC1,GC2,U1f,U1l,U2f,U2l);
179 for ( Standard_Integer i = 1; i <= Ex.NbExtrema(); i++)
180 {
181 gp_Pnt P1,P2;
182 Ex.Points(i,P1,P2);
183 Standard_Real dist = P1.Distance(P2);
184 if ( i == 1 )
185 {
186 mindist = dist;
187 PC1 = P1;
188 }
189 else
190 {
191 if ( (dist < mindist) || (dist < Precision::Confusion()) )
192 {
193 mindist = dist;
194 PC1 = P1;
195 }
196 }
197 if ( dist < Precision::Confusion() )
198 {
199 if (GC1->IsInstance(STANDARD_TYPE(Geom_Line)))
200 {
201 continue; // tangent line and conic can have only one point with zero distance
202 }
203 gp_Vec aVector1,aVector2;
204 if (GC1->IsInstance(STANDARD_TYPE(Geom_Circle)))
205 {
c5f3a425 206 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (GC1));
7fd59977 207 Standard_Real par_inter = ElCLib::Parameter(circle->Circ(), P1);
208 ElCLib::D1(par_inter,circle->Circ(),P1,aVector1);
209 }
210 else if (GC1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
211 {
c5f3a425 212 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (GC1));
7fd59977 213 Standard_Real par_inter = ElCLib::Parameter(ellipse->Elips(), P1);
214 ElCLib::D1(par_inter,ellipse->Elips(),P1,aVector1);
215 }
216 if (GC2->IsInstance(STANDARD_TYPE(Geom_Circle)))
217 {
c5f3a425 218 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (GC2));
7fd59977 219 Standard_Real par_inter = ElCLib::Parameter(circle->Circ(), P2);
220 ElCLib::D1(par_inter,circle->Circ(),P2,aVector2);
221 }
222 else if (GC2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
223 {
c5f3a425 224 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (GC2));
7fd59977 225 Standard_Real par_inter = ElCLib::Parameter(ellipse->Elips(), P2);
226 ElCLib::D1(par_inter,ellipse->Elips(),P2,aVector2);
227 }
228// if ( aVector1.IsParallel(aVector2, 100*Precision::Angular()) ) break;
c6541a0c 229 if ( aVector1.IsParallel(aVector2, M_PI / 360.0) ) break; // 0.5 graduce
7fd59977 230 }
231 }
232 aPoint = PC1;
233 return Standard_True;
234}
235// jfa 19/10/2000 end
236
237//=======================================================================
238//function : ComputeTwoEdgesTangent
239//purpose :
240//=======================================================================
241void AIS_TangentRelation::ComputeTwoEdgesTangent(const Handle(Prs3d_Presentation)& aPresentation)
242{
243 Handle(Geom_Curve) copy1,copy2;
244 gp_Pnt ptat11,ptat12,ptat21,ptat22;
245 Standard_Boolean isInfinite1,isInfinite2;
246 Handle(Geom_Curve) extCurv;
247 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
248 TopoDS::Edge(mySShape),
249 myExtShape,
250 copy1,
251 copy2,
252 ptat11,
253 ptat12,
254 ptat21,
255 ptat22,
256 extCurv,
257 isInfinite1,isInfinite2,
258 myPlane))
259 {
260 return;
261 }
262
263 aPresentation->SetInfiniteState(isInfinite1 || isInfinite2);
264 // current face
265 BRepBuilderAPI_MakeFace makeface(myPlane->Pln());
266 TopoDS_Face face(makeface.Face());
267 BRepAdaptor_Surface adp(makeface.Face());
268
269 Standard_Integer typArg(0);
270
271 if (copy1->IsInstance(STANDARD_TYPE(Geom_Line)))
272 {
273 typArg = 10;
274 }
275 else if (copy1->IsInstance(STANDARD_TYPE(Geom_Circle)))
276 {
277 typArg = 20;
278 }
279 else if (copy1->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
280 {
281 typArg = 30;
282 }
283 else return;
284
285 if (copy2->IsInstance(STANDARD_TYPE(Geom_Line)))
286 {
287 typArg += 1;
288 }
289 else if (copy2->IsInstance(STANDARD_TYPE(Geom_Circle)))
290 {
291 typArg += 2;
292 }
293 else if (copy2->IsInstance(STANDARD_TYPE(Geom_Ellipse)))
294 {
295 typArg += 3;
296 }
297 else return;
298
0d969553 299 //First find the tangengy vector if exists
7fd59977 300 TopoDS_Vertex VCom;
301 TopExp_Explorer expF(TopoDS::Edge(myFShape),TopAbs_VERTEX);
302 TopExp_Explorer expS(TopoDS::Edge(mySShape),TopAbs_VERTEX);
303 TopoDS_Shape tab[2];
304 Standard_Integer p ;
305 for (p = 0; expF.More(); expF.Next(),p++)
306 {
307 tab[p] = TopoDS::Vertex(expF.Current());
308 }
309 Standard_Boolean found(Standard_False);
310 for ( ; expS.More() && !found; expS.Next())
311 {
312 for ( Standard_Integer l = 0; l<=p && !found; l++)
313 {
314 found = ( expS.Current().IsSame(tab[l]));
315 if (found) VCom = TopoDS::Vertex(expS.Current());
316 }
317 }
318
319 gp_Vec theVector;
81bba717 320 gp_Pnt pint3d; // tangency point
321 gp_Dir theDir; // tangency direction
7fd59977 322 Standard_Real par_inter = 0.0; // parameter of tangency point
323
324 if (found)
325 {
326 pint3d = BRep_Tool::Pnt(VCom);
327 }
328
81bba717 329 // Otherwise it is found as if it was known that 2 curves
330 // are tangents (which must be the cases)
7fd59977 331 switch (typArg)
332 {
81bba717 333 case 12: // circle line
334 {
c5f3a425 335 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy1));
336 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy2));
7fd59977 337
338 if ( !found )
339 {
81bba717 340 // it is enough to project the circus center on the straight line
7fd59977 341 par_inter = ElCLib::Parameter(line->Lin(), circle->Location());
342 pint3d = ElCLib::Value(par_inter, line->Lin());
343 }
344
345 theDir = line->Lin().Direction();
346 myLength = circle->Radius()/5.;
347 if ( !isInfinite1 )
348 {
349 Standard_Real copy1Length = ptat12.Distance(ptat11);
350 if ( copy1Length < myLength )
351 myLength = copy1Length/3.;
352 }
353 }
354 break;
355 case 21: // circle line
356 {
c5f3a425 357 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy1));
358 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy2));
7fd59977 359
360 if (!found)
361 {
81bba717 362 // it is enough to project the circus center on the straight line
7fd59977 363 par_inter = ElCLib::Parameter(line->Lin(), circle->Location());
364 pint3d = ElCLib::Value(par_inter, line->Lin());
365 }
366
367 theDir = line->Lin().Direction();
368 myLength = circle->Radius()/5.;
369 if (!isInfinite2)
370 {
371 Standard_Real copy2Length = ptat21.Distance(ptat22);
372 if ( copy2Length < myLength )
373 myLength = copy2Length/3.;
374 }
375 }
376 break;
377 // jfa 19/10/2000 begin
378 case 13: // line ellipse
379 {
c5f3a425 380 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy1));
381 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy2));
7fd59977 382
383 if (!found)
384 {
385 ComputeTangencyPoint(line,ellipse,pint3d);
386 }
387
388 theDir = line->Lin().Direction();
389 myLength = ellipse->MajorRadius()/5.;
390
391 if (!isInfinite1)
392 {
393 Standard_Real copy1Length = ptat12.Distance(ptat11);
394 if ( copy1Length < myLength )
395 myLength = copy1Length/3.;
396 }
397 }
398 break;
399 case 31: // ellipse line
400 {
c5f3a425 401 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy1));
402 Handle(Geom_Line) line (Handle(Geom_Line)::DownCast (copy2));
7fd59977 403
404 if (!found)
405 {
406 ComputeTangencyPoint(line,ellipse,pint3d);
407 }
408
409 theDir = line->Lin().Direction();
410 myLength = ellipse->MajorRadius()/5.;
411
412 if (!isInfinite2)
413 {
414 Standard_Real copy2Length = ptat21.Distance(ptat22);
415 if ( copy2Length < myLength )
416 myLength = copy2Length/3.;
417 }
418 }
419 break;
420 case 22: // circle circle
421 {
c5f3a425 422 Handle(Geom_Circle) circle1 (Handle(Geom_Circle)::DownCast (copy1));
423 Handle(Geom_Circle) circle2 (Handle(Geom_Circle)::DownCast (copy2));
7fd59977 424 Standard_Real R1 = circle1->Radius();
425 Standard_Real R2 = circle2->Radius();
426 myLength = Max(R1,R2)/5.0;
427 if ( !found )
428 {
429 if ( (circle1->Location()).IsEqual(circle2->Location(),Precision::Confusion()) )
430 {
431 if ( R1 >= R2 )
432 {
433 ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
434 }
435 else
436 {
437 ElCLib::D1(par_inter,circle2->Circ(),pint3d,theVector);
438 }
439 }
440 else
441 {
442 if ( R1 >= R2 )
443 {
444 par_inter = ElCLib::Parameter(circle1->Circ(), circle2->Location());
445 ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
446 }
447 else
448 {
449 par_inter = ElCLib::Parameter(circle2->Circ(), circle1->Location());
450 ElCLib::D1(par_inter,circle2->Circ(),pint3d,theVector);
451 }
452 }
453 }
454 else
455 {
456 par_inter = ElCLib::Parameter(circle1->Circ(), pint3d);
457 ElCLib::D1(par_inter,circle1->Circ(),pint3d,theVector);
458 }
459 theDir = gp_Dir(theVector);
460 }
461 break;
462 case 23: // circle ellipse
463 {
c5f3a425 464 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy1));
465 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy2));
7fd59977 466 Standard_Real R1 = circle->Radius();
467 Standard_Real R2 = ellipse->MajorRadius();
468 myLength = Max(R1,R2)/5.0;
469 if (!found)
470 {
471 if ( R1 >= R2 )
472 {
473 ComputeTangencyPoint(circle,ellipse,pint3d);
474 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
475 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
476 }
477 else
478 {
479 ComputeTangencyPoint(ellipse,circle,pint3d);
480 par_inter = ElCLib::Parameter(ellipse->Elips(), pint3d);
481 ElCLib::D1(par_inter,ellipse->Elips(),pint3d,theVector);
482 }
483 }
484 else
485 {
486 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
487 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
488 }
489 theDir = gp_Dir(theVector);
490 }
491 break;
492 case 32: // ellipse circle
493 {
c5f3a425 494 Handle(Geom_Ellipse) ellipse (Handle(Geom_Ellipse)::DownCast (copy1));
495 Handle(Geom_Circle) circle (Handle(Geom_Circle)::DownCast (copy2));
7fd59977 496 Standard_Real R1 = ellipse->MajorRadius();
497 Standard_Real R2 = circle->Radius();
498 myLength = Max(R1,R2)/5.0;
499 if (!found)
500 {
501 if ( R1 >= R2 )
502 {
503 ComputeTangencyPoint(ellipse,circle,pint3d);
504 par_inter = ElCLib::Parameter( ellipse->Elips(), pint3d);
505 ElCLib::D1(par_inter,ellipse->Elips(),pint3d,theVector);
506 }
507 else
508 {
509 ComputeTangencyPoint(circle,ellipse,pint3d);
510 par_inter = ElCLib::Parameter( circle->Circ(), pint3d);
511 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
512 }
513 }
514 else
515 {
516 par_inter = ElCLib::Parameter(circle->Circ(), pint3d);
517 ElCLib::D1(par_inter,circle->Circ(),pint3d,theVector);
518 }
519 theDir = gp_Dir(theVector);
520 }
521 break;
522 case 33: // ellipse ellipse
523 {
c5f3a425 524 Handle(Geom_Ellipse) ellipse1 (Handle(Geom_Ellipse)::DownCast (copy1));
525 Handle(Geom_Ellipse) ellipse2 (Handle(Geom_Ellipse)::DownCast (copy2));
7fd59977 526 Standard_Real R1 = ellipse1->MajorRadius();
527 Standard_Real R2 = ellipse2->MajorRadius();
528 myLength = Max(R1,R2)/5.0;
529 if (!found)
530 {
531 if ( R1 > R2 )
532 {
533 ComputeTangencyPoint(ellipse1,ellipse2,pint3d);
534 par_inter = ElCLib::Parameter( ellipse1->Elips(), pint3d);
535 ElCLib::D1(par_inter,ellipse1->Elips(),pint3d,theVector);
536 }
537 else
538 {
539 ComputeTangencyPoint(ellipse2,ellipse1,pint3d);
540 par_inter = ElCLib::Parameter( ellipse2->Elips(), pint3d);
541 ElCLib::D1(par_inter,ellipse2->Elips(),pint3d,theVector);
542 }
543 }
544 else
545 {
546 par_inter = ElCLib::Parameter(ellipse1->Elips(), pint3d);
547 ElCLib::D1(par_inter,ellipse1->Elips(),pint3d,theVector);
548 }
549 theDir = gp_Dir(theVector);
550 }
551 break;
552 // jfa 19/10/2000 end
553 default:
554 return;
555 }
556
557 myAttach = pint3d;
558 myDir = theDir;
559 myPosition = pint3d;
560 myLength = Min(myLength,myArrowSize);
561
562 DsgPrs_TangentPresentation::Add(aPresentation,myDrawer,myAttach,myDir,myLength);
563 if ( (myExtShape != 0) && !extCurv.IsNull())
564 {
565 gp_Pnt pf, pl;
566 if ( myExtShape == 1 )
567 {
568 if (!isInfinite1)
569 {
570 pf = ptat11;
571 pl = ptat12;
572 }
573 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(myFShape),copy1,pf,pl);
574 }
575 else
576 {
577 if (!isInfinite2)
578 {
579 pf = ptat21;
580 pl = ptat22;
581 }
582 ComputeProjEdgePresentation(aPresentation,TopoDS::Edge(mySShape),copy2,pf,pl);
583 }
584 }
585}