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)
85 if (myTool.ShapeType() == TopAbs_VERTEX)
88 Standard_Boolean isonplane;
89 if ( AIS::ComputeGeometry(TopoDS::Vertex(myTool),pp,myPlane,isonplane) )
91 if ( !isonplane ) ComputeProjVertexPresentation(aprs,TopoDS::Vertex(myTool),pp);
97 if ( myAutomaticPosition ) myPosition = myMidPoint;
99 switch (myFShape.ShapeType())
103 ComputeFaceFromPnt(aprs, Standard_True);
108 ComputeEdgeFromPnt(aprs, Standard_True);
113 ComputeVertexFromPnt(aprs, Standard_True);
120 switch (mySShape.ShapeType())
124 ComputeFaceFromPnt(aprs, Standard_False);
129 ComputeEdgeFromPnt(aprs, Standard_False);
134 ComputeVertexFromPnt(aprs, Standard_False);
142 //=======================================================================
144 //purpose : to avoid warning at compilation (SUN)
145 //=======================================================================
146 void AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)& /*aProjector*/,
147 const Handle(Prs3d_Presentation)& /*aPresentation*/)
149 // Standard_NotImplemented::Raise("AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
150 // PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
153 void AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
154 const Handle(Geom_Transformation)& aTransformation,
155 const Handle(Prs3d_Presentation)& aPresentation)
157 Standard_NotImplemented::Raise("AIS_MidPointRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
158 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
161 //=======================================================================
162 //function : ComputeSelection
164 //=======================================================================
165 void AIS_MidPointRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSel,
166 const Standard_Integer)
168 Handle(Select3D_SensitiveSegment) seg;
169 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
171 if ( !myMidPoint.IsEqual(myFAttach,Precision::Confusion()) )
173 // segment from mid point to the first geometry
174 seg = new Select3D_SensitiveSegment(own,myFAttach,myMidPoint);
176 // segment from mid point to the second geometry
177 seg = new Select3D_SensitiveSegment(own,mySAttach,myMidPoint);
180 if ( !myMidPoint.IsEqual(myPosition,Precision::Confusion()) )
182 // segment from mid point to the text position
183 seg = new Select3D_SensitiveSegment(own,myMidPoint,myPosition);
187 // center of the symmetry - circle around the MidPoint
188 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
189 ax.SetLocation(myMidPoint);
190 Standard_Real rad = myFAttach.Distance(myMidPoint)/20.0;
191 gp_Circ aCircleM (ax,rad);
192 Handle(Geom_Curve) thecir = new Geom_Circle(aCircleM);
193 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecir);
196 Handle(Geom_Curve) curv;
198 Standard_Boolean isInfinite,isOnPlane;
199 Handle(Geom_Curve) extCurv;
201 // segment on first curve
202 if ( myFShape.ShapeType() == TopAbs_EDGE )
204 TopoDS_Edge E = TopoDS::Edge(myFShape);
205 if ( !AIS::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
206 if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
209 seg = new Select3D_SensitiveSegment(own,myFirstPnt1,myFirstPnt2);
212 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
215 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
216 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFirstPnt1);
217 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),myFirstPnt2);
218 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
220 scurv = new Select3D_SensitiveCurve(own, thecu);
223 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
225 // segment on ellipse
226 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
227 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFirstPnt1);
228 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),myFirstPnt2);
229 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
231 scurv = new Select3D_SensitiveCurve(own, thecu);
236 // segment on second curve
237 if ( mySShape.ShapeType() == TopAbs_EDGE )
239 TopoDS_Edge E = TopoDS::Edge(mySShape);
240 if ( !AIS::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
241 if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
244 seg = new Select3D_SensitiveSegment(own,mySecondPnt1,mySecondPnt2);
247 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
250 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
251 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),mySecondPnt1);
252 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySecondPnt2);
253 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
255 scurv = new Select3D_SensitiveCurve(own, thecu);
258 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
260 // segment on ellipse
261 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
262 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),mySecondPnt1);
263 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySecondPnt2);
264 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
266 scurv = new Select3D_SensitiveCurve(own, thecu);
272 //=======================================================================
273 //function : ComputeFaceFromPnt
275 //=======================================================================
276 void AIS_MidPointRelation::ComputeFaceFromPnt(const Handle(Prs3d_Presentation)&,
277 const Standard_Boolean /*first*/)
281 //=======================================================================
282 //function : ComputeEdgeFromPnt
284 //=======================================================================
285 void AIS_MidPointRelation::ComputeEdgeFromPnt(const Handle(Prs3d_Presentation)& aprs,
286 const Standard_Boolean first)
289 if ( first ) E = TopoDS::Edge(myFShape);
290 else E = TopoDS::Edge(mySShape);
292 Handle(Geom_Curve) geom;
294 Handle(Geom_Curve) extCurv;
295 Standard_Boolean isInfinite,isOnPlane;
296 if ( !AIS::ComputeGeometry(E, geom, ptat1, ptat2, extCurv, isInfinite, isOnPlane, myPlane) ) return;
298 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
300 if ( geom->IsInstance(STANDARD_TYPE(Geom_Line)) )
302 if ( !isInfinite ) ComputePointsOnLine(ptat1,ptat2,first);
305 const gp_Lin& line = Handle(Geom_Line)::DownCast (geom)->Lin();
306 ComputePointsOnLine(line,first);
308 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
309 myFAttach,myFirstPnt1,myFirstPnt2,first);
310 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
311 mySAttach,mySecondPnt1,mySecondPnt2,first);
313 else if ( geom->IsInstance(STANDARD_TYPE(Geom_Circle)) )
315 Handle(Geom_Circle) geom_cir (Handle(Geom_Circle)::DownCast (geom));
316 gp_Circ circ (geom_cir->Circ());
317 ComputePointsOnCirc(circ,ptat1,ptat2,first);
318 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
319 myFAttach,myFirstPnt1,myFirstPnt2,first);
320 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
321 mySAttach,mySecondPnt1,mySecondPnt2,first);
323 else if ( geom->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
325 Handle(Geom_Ellipse) geom_ell (Handle(Geom_Ellipse)::DownCast (geom));
326 gp_Elips elips (geom_ell->Elips());
327 ComputePointsOnElips(elips,ptat1,ptat2,first);
328 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
329 myFAttach,myFirstPnt1,myFirstPnt2,first);
330 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
331 mySAttach,mySecondPnt1,mySecondPnt2,first);
335 // projection on myPlane
336 if ( !isOnPlane ) ComputeProjEdgePresentation(aprs,E,geom,ptat1,ptat2);
339 //=======================================================================
340 //function : ComputeVertexFromPnt
342 //=======================================================================
343 void AIS_MidPointRelation::ComputeVertexFromPnt(const Handle(Prs3d_Presentation)& aprs,
344 const Standard_Boolean first)
346 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
349 Standard_Boolean isOnPlane;
350 TopoDS_Vertex V = TopoDS::Vertex(myFShape);
351 AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlane);
352 DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,myFAttach,first);
353 if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,myFAttach);
357 Standard_Boolean isOnPlane;
358 TopoDS_Vertex V = TopoDS::Vertex(mySShape);
359 AIS::ComputeGeometry(V, mySAttach, myPlane, isOnPlane);
360 DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,mySAttach,first);
361 if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,mySAttach);
365 //=======================================================================
366 //function : ComputePointsOnLine
368 //=======================================================================
369 void AIS_MidPointRelation::ComputePointsOnLine(const gp_Lin& aLin,
370 const Standard_Boolean first)
372 Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
373 gp_Pnt anAttach = ElCLib::Value(ppar,aLin);
375 Standard_Real dist = anAttach.Distance(myMidPoint)/10.0;
376 if ( dist < Precision::Confusion() ) dist = 10.0;
378 Standard_Real fpar = ppar + dist;
379 Standard_Real spar = ppar - dist;
381 gp_Pnt aPnt1 = ElCLib::Value(fpar,aLin);
382 gp_Pnt aPnt2 = ElCLib::Value(spar,aLin);
386 myFAttach = anAttach;
392 mySAttach = anAttach;
393 mySecondPnt1 = aPnt1;
394 mySecondPnt2 = aPnt2;
398 //=======================================================================
399 //function : ComputePointsOnLine
401 //=======================================================================
402 void AIS_MidPointRelation::ComputePointsOnLine(const gp_Pnt& pnt1, const gp_Pnt& pnt2,
403 const Standard_Boolean first)
405 gp_Vec aVec (pnt1,pnt2);
406 gp_Lin aLin (pnt1,gp_Dir(aVec));
408 Standard_Real fpar = ElCLib::Parameter(aLin,pnt1);
409 Standard_Real spar = ElCLib::Parameter(aLin,pnt2);
410 Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
412 gp_Pnt aProjPnt = ElCLib::Value(ppar,aLin);
413 Standard_Real dist = myMidPoint.Distance(aProjPnt);
414 Standard_Real ll = pnt1.Distance(pnt2);
415 Standard_Real segm = Min(dist,ll)*0.75;
416 if ( dist < Precision::Confusion() ) segm = ll*0.75;
418 gp_Pnt anAttach,aPnt1,aPnt2;
424 aVecTr = gp_Vec(pnt2,pnt1);
426 aPnt1 = aProjPnt.Translated(aVecTr*segm);
428 else if ( ppar >= spar )
431 aVecTr = gp_Vec(pnt1,pnt2);
433 aPnt2 = aProjPnt.Translated(aVecTr*segm);
437 Standard_Real dp1 = aProjPnt.Distance(pnt1);
438 Standard_Real dp2 = aProjPnt.Distance(pnt2);
440 segm = Min(dist,dp1)*0.75;
441 aVecTr = gp_Vec(aProjPnt,pnt1);
443 aPnt1 = aProjPnt.Translated(aVecTr*segm);
445 segm = Min(dist,dp2)*0.75;
446 aVecTr = gp_Vec(aProjPnt,pnt2);
448 aPnt2 = aProjPnt.Translated(aVecTr*segm);
453 myFAttach = anAttach;
459 mySAttach = anAttach;
460 mySecondPnt1 = aPnt1;
461 mySecondPnt2 = aPnt2;
465 //=======================================================================
466 //function : ComputePointsOnCirc
468 //=======================================================================
469 void AIS_MidPointRelation::ComputePointsOnCirc(const gp_Circ& aCirc,
470 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
471 const Standard_Boolean first)
473 gp_Pnt curpos = myMidPoint;
475 // Case of confusion between the current position and the center
476 // of the circle -> we move the current position
477 Standard_Real confusion (Precision::Confusion());
478 gp_Pnt aCenter = aCirc.Location();
479 if ( aCenter.Distance(curpos) <= confusion )
481 gp_Vec vprec(aCenter, pnt1);
483 curpos.Translate(vprec*1e-5);
486 Standard_Real pcurpos = ElCLib::Parameter(aCirc,curpos);
488 Standard_Real rad = M_PI / 5.0;
494 if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
496 pFPnt = pcurpos - rad;
497 pSPnt = pcurpos + rad;
501 Standard_Real pFAttach = ElCLib::Parameter(aCirc,pnt1);
502 Standard_Real pSAttach = ElCLib::Parameter(aCirc,pnt2);
504 Standard_Real pSAttachM = pSAttach;
505 Standard_Real deltap = pSAttachM - pFAttach;
509 pSAttachM += 2 * M_PI;
511 pSAttachM -= pFAttach;
513 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
515 Standard_Real pcurpos1 = pcurpos;
516 // define where curpos lays
517 if ( pcurpos1 < pFAttach )
519 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
520 if ( pcurpos1 > pSAttachM ) // out
522 segm = Min(rad,deltap*0.75);
523 if ( pcurpos1 > pmiddleout )
527 pSPnt = pFAttach + segm;
532 pFPnt = pSAttach - segm;
538 Standard_Real dp1 = pcurpos1 - pFAttach;
539 Standard_Real dp2 = pSAttachM - pcurpos1;
541 segm = Min(rad,dp1*0.75);
542 pFPnt = pcurpos - segm;
544 segm = Min(rad,dp2*0.75);
545 pSPnt = pcurpos + segm;
548 else if ( pcurpos1 > (pFAttach + deltap) ) // out
550 pcurpos1 -= pFAttach;
551 segm = Min(rad,deltap*0.75);
552 if ( pcurpos1 > pmiddleout )
556 pSPnt = pFAttach + segm;
561 pFPnt = pSAttach - segm;
567 Standard_Real dp1 = pcurpos1 - pFAttach;
568 Standard_Real dp2 = pSAttach - pcurpos1;
570 segm = Min(rad,dp1*0.75);
571 pFPnt = pcurpos - segm;
573 segm = Min(rad,dp2*0.75);
574 pSPnt = pcurpos + segm;
580 myFAttach = ElCLib::Value(pcurpos,aCirc);
581 myFirstPnt1 = ElCLib::Value(pFPnt,aCirc);
582 myFirstPnt2 = ElCLib::Value(pSPnt,aCirc);
586 mySAttach = ElCLib::Value(pcurpos,aCirc);
587 mySecondPnt1 = ElCLib::Value(pFPnt,aCirc);
588 mySecondPnt2 = ElCLib::Value(pSPnt,aCirc);
592 //=======================================================================
593 //function : ComputePointsOnElips
595 //=======================================================================
596 void AIS_MidPointRelation::ComputePointsOnElips(const gp_Elips& anEll,
597 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
598 const Standard_Boolean first)
600 gp_Pnt curpos = myMidPoint;
602 // Case of confusion between the current position and the center
603 // of the circle -> we move the current position
604 Standard_Real confusion (Precision::Confusion());
605 gp_Pnt aCenter = anEll.Location();
606 if ( aCenter.Distance(curpos) <= confusion )
608 gp_Vec vprec(aCenter, pnt1);
610 curpos.Translate(vprec*1e-5);
613 Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
615 Standard_Real rad = M_PI / 5.0;
621 if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
623 pFPnt = pcurpos - rad;
624 pSPnt = pcurpos + rad;
628 Standard_Real pFAttach = ElCLib::Parameter(anEll,pnt1);
629 Standard_Real pSAttach = ElCLib::Parameter(anEll,pnt2);
631 Standard_Real pSAttachM = pSAttach;
632 Standard_Real deltap = pSAttachM - pFAttach;
636 pSAttachM += 2 * M_PI;
638 pSAttachM -= pFAttach;
640 Standard_Real pmiddleout = pSAttachM / 2.0 + M_PI;
642 Standard_Real pcurpos1 = pcurpos;
643 // define where curpos lays
644 if ( pcurpos1 < pFAttach )
646 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
647 if ( pcurpos1 > pSAttachM ) // out
649 segm = Min(rad,deltap*0.75);
650 if ( pcurpos1 > pmiddleout )
654 pSPnt = pFAttach + segm;
659 pFPnt = pSAttach - segm;
665 Standard_Real dp1 = pcurpos1 - pFAttach;
666 Standard_Real dp2 = pSAttachM - pcurpos1;
668 segm = Min(rad,dp1*0.75);
669 pFPnt = pcurpos - segm;
671 segm = Min(rad,dp2*0.75);
672 pSPnt = pcurpos + segm;
675 else if ( pcurpos1 > (pFAttach + deltap) ) // out
677 pcurpos1 -= pFAttach;
678 segm = Min(rad,deltap*0.75);
679 if ( pcurpos1 > pmiddleout )
683 pSPnt = pFAttach + segm;
688 pFPnt = pSAttach - segm;
694 Standard_Real dp1 = pcurpos1 - pFAttach;
695 Standard_Real dp2 = pSAttach - pcurpos1;
697 segm = Min(rad,dp1*0.75);
698 pFPnt = pcurpos - segm;
700 segm = Min(rad,dp2*0.75);
701 pSPnt = pcurpos + segm;
707 myFAttach = ElCLib::Value(pcurpos,anEll);
708 myFirstPnt1 = ElCLib::Value(pFPnt,anEll);
709 myFirstPnt2 = ElCLib::Value(pSPnt,anEll);
713 mySAttach = ElCLib::Value(pcurpos,anEll);
714 mySecondPnt1 = ElCLib::Value(pFPnt,anEll);
715 mySecondPnt2 = ElCLib::Value(pSPnt,anEll);