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