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