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