1 // Created on: 2000-10-20
2 // Created by: Julia DOROVSKIKH
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
18 #include <AIS_MidPointRelation.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Curve.hxx>
21 #include <BRepAdaptor_Surface.hxx>
22 #include <DsgPrs_MidPointPresentation.hxx>
24 #include <gce_MakeLin.hxx>
25 #include <Geom_Circle.hxx>
26 #include <Geom_Ellipse.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Plane.hxx>
29 #include <Geom_Transformation.hxx>
30 #include <Geom_TrimmedCurve.hxx>
33 #include <gp_Circ.hxx>
35 #include <gp_Elips.hxx>
39 #include <Precision.hxx>
40 #include <Prs3d_ArrowAspect.hxx>
41 #include <Prs3d_DimensionAspect.hxx>
42 #include <Prs3d_Drawer.hxx>
43 #include <Prs3d_Presentation.hxx>
44 #include <Prs3d_Projector.hxx>
45 #include <Select3D_SensitiveCurve.hxx>
46 #include <Select3D_SensitiveSegment.hxx>
47 #include <SelectMgr_EntityOwner.hxx>
48 #include <SelectMgr_Selection.hxx>
49 #include <Standard_NotImplemented.hxx>
50 #include <Standard_Type.hxx>
51 #include <TopExp_Explorer.hxx>
53 #include <TopoDS_Shape.hxx>
54 #include <TopoDS_Vertex.hxx>
56 IMPLEMENT_STANDARD_RTTIEXT(AIS_MidPointRelation,AIS_Relation)
58 //=======================================================================
59 //function : AIS_MidPointRelation
61 //=======================================================================
62 AIS_MidPointRelation::AIS_MidPointRelation(const TopoDS_Shape& aMidPointTool,
63 const TopoDS_Shape& FirstShape,
64 const TopoDS_Shape& SecondShape,
65 const Handle(Geom_Plane)& aPlane)
69 SetFirstShape(FirstShape);
70 SetSecondShape(SecondShape);
72 myPosition = aPlane->Pln().Location();
75 //=======================================================================
78 //=======================================================================
79 void AIS_MidPointRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
80 const Handle(Prs3d_Presentation)& aprs,
81 const Standard_Integer)
83 if (myTool.ShapeType() == TopAbs_VERTEX)
86 Standard_Boolean isonplane;
87 if ( AIS::ComputeGeometry(TopoDS::Vertex(myTool),pp,myPlane,isonplane) )
89 if ( !isonplane ) ComputeProjVertexPresentation(aprs,TopoDS::Vertex(myTool),pp);
95 if ( myAutomaticPosition ) myPosition = myMidPoint;
97 switch (myFShape.ShapeType())
101 ComputeFaceFromPnt(aprs, Standard_True);
106 ComputeEdgeFromPnt(aprs, Standard_True);
111 ComputeVertexFromPnt(aprs, Standard_True);
118 switch (mySShape.ShapeType())
122 ComputeFaceFromPnt(aprs, Standard_False);
127 ComputeEdgeFromPnt(aprs, Standard_False);
132 ComputeVertexFromPnt(aprs, Standard_False);
140 //=======================================================================
142 //purpose : to avoid warning at compilation (SUN)
143 //=======================================================================
144 void AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)& /*aProjector*/,
145 const Handle(Prs3d_Presentation)& /*aPresentation*/)
147 // Standard_NotImplemented::Raise("AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
148 // PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
151 void AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
152 const Handle(Geom_Transformation)& aTransformation,
153 const Handle(Prs3d_Presentation)& aPresentation)
155 Standard_NotImplemented::Raise("AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
156 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
159 //=======================================================================
160 //function : ComputeSelection
162 //=======================================================================
163 void AIS_MidPointRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSel,
164 const Standard_Integer)
166 Handle(Select3D_SensitiveSegment) seg;
167 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
169 if ( !myMidPoint.IsEqual(myFAttach,Precision::Confusion()) )
171 // segment from mid point to the first geometry
172 seg = new Select3D_SensitiveSegment(own,myFAttach,myMidPoint);
174 // segment from mid point to the second geometry
175 seg = new Select3D_SensitiveSegment(own,mySAttach,myMidPoint);
178 if ( !myMidPoint.IsEqual(myPosition,Precision::Confusion()) )
180 // segment from mid point to the text position
181 seg = new Select3D_SensitiveSegment(own,myMidPoint,myPosition);
185 // center of the symmetry - circle around the MidPoint
186 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
187 ax.SetLocation(myMidPoint);
188 Standard_Real rad = myFAttach.Distance(myMidPoint)/20.0;
189 gp_Circ aCircleM (ax,rad);
190 Handle(Geom_Curve) thecir = new Geom_Circle(aCircleM);
191 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecir);
194 Handle(Geom_Curve) curv;
196 Standard_Boolean isInfinite,isOnPlane;
197 Handle(Geom_Curve) extCurv;
199 // segment on first curve
200 if ( myFShape.ShapeType() == TopAbs_EDGE )
202 TopoDS_Edge E = TopoDS::Edge(myFShape);
203 if ( !AIS::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
204 if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
207 seg = new Select3D_SensitiveSegment(own,myFirstPnt1,myFirstPnt2);
210 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
213 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
214 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFirstPnt1);
215 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),myFirstPnt2);
216 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
218 scurv = new Select3D_SensitiveCurve(own, thecu);
221 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
223 // segment on ellipse
224 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
225 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFirstPnt1);
226 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),myFirstPnt2);
227 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
229 scurv = new Select3D_SensitiveCurve(own, thecu);
234 // segment on second curve
235 if ( mySShape.ShapeType() == TopAbs_EDGE )
237 TopoDS_Edge E = TopoDS::Edge(mySShape);
238 if ( !AIS::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
239 if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
242 seg = new Select3D_SensitiveSegment(own,mySecondPnt1,mySecondPnt2);
245 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
248 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
249 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),mySecondPnt1);
250 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySecondPnt2);
251 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
253 scurv = new Select3D_SensitiveCurve(own, thecu);
256 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
258 // segment on ellipse
259 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
260 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),mySecondPnt1);
261 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySecondPnt2);
262 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
264 scurv = new Select3D_SensitiveCurve(own, thecu);
270 //=======================================================================
271 //function : ComputeFaceFromPnt
273 //=======================================================================
274 void AIS_MidPointRelation::ComputeFaceFromPnt(const Handle(Prs3d_Presentation)&,
275 const Standard_Boolean /*first*/)
279 //=======================================================================
280 //function : ComputeEdgeFromPnt
282 //=======================================================================
283 void AIS_MidPointRelation::ComputeEdgeFromPnt(const Handle(Prs3d_Presentation)& aprs,
284 const Standard_Boolean first)
287 if ( first ) E = TopoDS::Edge(myFShape);
288 else E = TopoDS::Edge(mySShape);
290 Handle(Geom_Curve) geom;
292 Handle(Geom_Curve) extCurv;
293 Standard_Boolean isInfinite,isOnPlane;
294 if ( !AIS::ComputeGeometry(E, geom, ptat1, ptat2, extCurv, isInfinite, isOnPlane, myPlane) ) return;
296 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
298 if ( geom->IsInstance(STANDARD_TYPE(Geom_Line)) )
300 if ( !isInfinite ) ComputePointsOnLine(ptat1,ptat2,first);
303 const gp_Lin& line = Handle(Geom_Line)::DownCast (geom)->Lin();
304 ComputePointsOnLine(line,first);
306 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
307 myFAttach,myFirstPnt1,myFirstPnt2,first);
308 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
309 mySAttach,mySecondPnt1,mySecondPnt2,first);
311 else if ( geom->IsInstance(STANDARD_TYPE(Geom_Circle)) )
313 Handle(Geom_Circle) geom_cir (Handle(Geom_Circle)::DownCast (geom));
314 gp_Circ circ (geom_cir->Circ());
315 ComputePointsOnCirc(circ,ptat1,ptat2,first);
316 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
317 myFAttach,myFirstPnt1,myFirstPnt2,first);
318 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
319 mySAttach,mySecondPnt1,mySecondPnt2,first);
321 else if ( geom->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
323 Handle(Geom_Ellipse) geom_ell (Handle(Geom_Ellipse)::DownCast (geom));
324 gp_Elips elips (geom_ell->Elips());
325 ComputePointsOnElips(elips,ptat1,ptat2,first);
326 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
327 myFAttach,myFirstPnt1,myFirstPnt2,first);
328 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
329 mySAttach,mySecondPnt1,mySecondPnt2,first);
333 // projection on myPlane
334 if ( !isOnPlane ) ComputeProjEdgePresentation(aprs,E,geom,ptat1,ptat2);
337 //=======================================================================
338 //function : ComputeVertexFromPnt
340 //=======================================================================
341 void AIS_MidPointRelation::ComputeVertexFromPnt(const Handle(Prs3d_Presentation)& aprs,
342 const Standard_Boolean first)
344 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
347 Standard_Boolean isOnPlane;
348 TopoDS_Vertex V = TopoDS::Vertex(myFShape);
349 AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlane);
350 DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,myFAttach,first);
351 if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,myFAttach);
355 Standard_Boolean isOnPlane;
356 TopoDS_Vertex V = TopoDS::Vertex(mySShape);
357 AIS::ComputeGeometry(V, mySAttach, myPlane, isOnPlane);
358 DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,mySAttach,first);
359 if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,mySAttach);
363 //=======================================================================
364 //function : ComputePointsOnLine
366 //=======================================================================
367 void AIS_MidPointRelation::ComputePointsOnLine(const gp_Lin& aLin,
368 const Standard_Boolean first)
370 Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
371 gp_Pnt anAttach = ElCLib::Value(ppar,aLin);
373 Standard_Real dist = anAttach.Distance(myMidPoint)/10.0;
374 if ( dist < Precision::Confusion() ) dist = 10.0;
376 Standard_Real fpar = ppar + dist;
377 Standard_Real spar = ppar - dist;
379 gp_Pnt aPnt1 = ElCLib::Value(fpar,aLin);
380 gp_Pnt aPnt2 = ElCLib::Value(spar,aLin);
384 myFAttach = anAttach;
390 mySAttach = anAttach;
391 mySecondPnt1 = aPnt1;
392 mySecondPnt2 = aPnt2;
396 //=======================================================================
397 //function : ComputePointsOnLine
399 //=======================================================================
400 void AIS_MidPointRelation::ComputePointsOnLine(const gp_Pnt& pnt1, const gp_Pnt& pnt2,
401 const Standard_Boolean first)
403 gp_Vec aVec (pnt1,pnt2);
404 gp_Lin aLin (pnt1,gp_Dir(aVec));
406 Standard_Real fpar = ElCLib::Parameter(aLin,pnt1);
407 Standard_Real spar = ElCLib::Parameter(aLin,pnt2);
408 Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
410 gp_Pnt aProjPnt = ElCLib::Value(ppar,aLin);
411 Standard_Real dist = myMidPoint.Distance(aProjPnt);
412 Standard_Real ll = pnt1.Distance(pnt2);
413 Standard_Real segm = Min(dist,ll)*0.75;
414 if ( dist < Precision::Confusion() ) segm = ll*0.75;
416 gp_Pnt anAttach,aPnt1,aPnt2;
422 aVecTr = gp_Vec(pnt2,pnt1);
424 aPnt1 = aProjPnt.Translated(aVecTr*segm);
426 else if ( ppar >= spar )
429 aVecTr = gp_Vec(pnt1,pnt2);
431 aPnt2 = aProjPnt.Translated(aVecTr*segm);
435 Standard_Real dp1 = aProjPnt.Distance(pnt1);
436 Standard_Real dp2 = aProjPnt.Distance(pnt2);
438 segm = Min(dist,dp1)*0.75;
439 aVecTr = gp_Vec(aProjPnt,pnt1);
441 aPnt1 = aProjPnt.Translated(aVecTr*segm);
443 segm = Min(dist,dp2)*0.75;
444 aVecTr = gp_Vec(aProjPnt,pnt2);
446 aPnt2 = aProjPnt.Translated(aVecTr*segm);
451 myFAttach = anAttach;
457 mySAttach = anAttach;
458 mySecondPnt1 = aPnt1;
459 mySecondPnt2 = aPnt2;
463 //=======================================================================
464 //function : ComputePointsOnCirc
466 //=======================================================================
467 void AIS_MidPointRelation::ComputePointsOnCirc(const gp_Circ& aCirc,
468 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
469 const Standard_Boolean first)
471 gp_Pnt curpos = myMidPoint;
473 // Case of confusion between the current position and the center
474 // of the circle -> we move the current position
475 Standard_Real confusion (Precision::Confusion());
476 gp_Pnt aCenter = aCirc.Location();
477 if ( aCenter.Distance(curpos) <= confusion )
479 gp_Vec vprec(aCenter, pnt1);
481 curpos.Translate(vprec*1e-5);
484 Standard_Real pcurpos = ElCLib::Parameter(aCirc,curpos);
486 Standard_Real rad = M_PI / 5.0;
492 if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
494 pFPnt = pcurpos - rad;
495 pSPnt = pcurpos + rad;
499 Standard_Real pFAttach = ElCLib::Parameter(aCirc,pnt1);
500 Standard_Real pSAttach = ElCLib::Parameter(aCirc,pnt2);
502 Standard_Real pSAttachM = pSAttach;
503 Standard_Real deltap = pSAttachM - pFAttach;
507 pSAttachM += 2 * M_PI;
509 pSAttachM -= pFAttach;
511 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
513 Standard_Real pcurpos1 = pcurpos;
514 // define where curpos lays
515 if ( pcurpos1 < pFAttach )
517 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
518 if ( pcurpos1 > pSAttachM ) // out
520 segm = Min(rad,deltap*0.75);
521 if ( pcurpos1 > pmiddleout )
525 pSPnt = pFAttach + segm;
530 pFPnt = pSAttach - segm;
536 Standard_Real dp1 = pcurpos1 - pFAttach;
537 Standard_Real dp2 = pSAttachM - pcurpos1;
539 segm = Min(rad,dp1*0.75);
540 pFPnt = pcurpos - segm;
542 segm = Min(rad,dp2*0.75);
543 pSPnt = pcurpos + segm;
546 else if ( pcurpos1 > (pFAttach + deltap) ) // out
548 pcurpos1 -= pFAttach;
549 segm = Min(rad,deltap*0.75);
550 if ( pcurpos1 > pmiddleout )
554 pSPnt = pFAttach + segm;
559 pFPnt = pSAttach - segm;
565 Standard_Real dp1 = pcurpos1 - pFAttach;
566 Standard_Real dp2 = pSAttach - pcurpos1;
568 segm = Min(rad,dp1*0.75);
569 pFPnt = pcurpos - segm;
571 segm = Min(rad,dp2*0.75);
572 pSPnt = pcurpos + segm;
578 myFAttach = ElCLib::Value(pcurpos,aCirc);
579 myFirstPnt1 = ElCLib::Value(pFPnt,aCirc);
580 myFirstPnt2 = ElCLib::Value(pSPnt,aCirc);
584 mySAttach = ElCLib::Value(pcurpos,aCirc);
585 mySecondPnt1 = ElCLib::Value(pFPnt,aCirc);
586 mySecondPnt2 = ElCLib::Value(pSPnt,aCirc);
590 //=======================================================================
591 //function : ComputePointsOnElips
593 //=======================================================================
594 void AIS_MidPointRelation::ComputePointsOnElips(const gp_Elips& anEll,
595 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
596 const Standard_Boolean first)
598 gp_Pnt curpos = myMidPoint;
600 // Case of confusion between the current position and the center
601 // of the circle -> we move the current position
602 Standard_Real confusion (Precision::Confusion());
603 gp_Pnt aCenter = anEll.Location();
604 if ( aCenter.Distance(curpos) <= confusion )
606 gp_Vec vprec(aCenter, pnt1);
608 curpos.Translate(vprec*1e-5);
611 Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
613 Standard_Real rad = M_PI / 5.0;
619 if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
621 pFPnt = pcurpos - rad;
622 pSPnt = pcurpos + rad;
626 Standard_Real pFAttach = ElCLib::Parameter(anEll,pnt1);
627 Standard_Real pSAttach = ElCLib::Parameter(anEll,pnt2);
629 Standard_Real pSAttachM = pSAttach;
630 Standard_Real deltap = pSAttachM - pFAttach;
634 pSAttachM += 2 * M_PI;
636 pSAttachM -= pFAttach;
638 Standard_Real pmiddleout = pSAttachM / 2.0 + M_PI;
640 Standard_Real pcurpos1 = pcurpos;
641 // define where curpos lays
642 if ( pcurpos1 < pFAttach )
644 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
645 if ( pcurpos1 > pSAttachM ) // out
647 segm = Min(rad,deltap*0.75);
648 if ( pcurpos1 > pmiddleout )
652 pSPnt = pFAttach + segm;
657 pFPnt = pSAttach - segm;
663 Standard_Real dp1 = pcurpos1 - pFAttach;
664 Standard_Real dp2 = pSAttachM - pcurpos1;
666 segm = Min(rad,dp1*0.75);
667 pFPnt = pcurpos - segm;
669 segm = Min(rad,dp2*0.75);
670 pSPnt = pcurpos + segm;
673 else if ( pcurpos1 > (pFAttach + deltap) ) // out
675 pcurpos1 -= pFAttach;
676 segm = Min(rad,deltap*0.75);
677 if ( pcurpos1 > pmiddleout )
681 pSPnt = pFAttach + segm;
686 pFPnt = pSAttach - segm;
692 Standard_Real dp1 = pcurpos1 - pFAttach;
693 Standard_Real dp2 = pSAttach - pcurpos1;
695 segm = Min(rad,dp1*0.75);
696 pFPnt = pcurpos - segm;
698 segm = Min(rad,dp2*0.75);
699 pSPnt = pcurpos + segm;
705 myFAttach = ElCLib::Value(pcurpos,anEll);
706 myFirstPnt1 = ElCLib::Value(pFPnt,anEll);
707 myFirstPnt2 = ElCLib::Value(pSPnt,anEll);
711 mySAttach = ElCLib::Value(pcurpos,anEll);
712 mySecondPnt1 = ElCLib::Value(pFPnt,anEll);
713 mySecondPnt2 = ElCLib::Value(pSPnt,anEll);