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