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.
16 #include <PrsDim_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_TrimmedCurve.hxx>
32 #include <gp_Circ.hxx>
34 #include <gp_Elips.hxx>
38 #include <Precision.hxx>
39 #include <Prs3d_ArrowAspect.hxx>
40 #include <Prs3d_DimensionAspect.hxx>
41 #include <Prs3d_Drawer.hxx>
42 #include <Prs3d_Presentation.hxx>
43 #include <Select3D_SensitiveCurve.hxx>
44 #include <Select3D_SensitiveSegment.hxx>
45 #include <SelectMgr_EntityOwner.hxx>
46 #include <SelectMgr_Selection.hxx>
47 #include <Standard_NotImplemented.hxx>
48 #include <TopExp_Explorer.hxx>
50 #include <TopoDS_Shape.hxx>
51 #include <TopoDS_Vertex.hxx>
53 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_MidPointRelation, PrsDim_Relation)
55 //=======================================================================
56 //function : PrsDim_MidPointRelation
58 //=======================================================================
59 PrsDim_MidPointRelation::PrsDim_MidPointRelation(const TopoDS_Shape& aMidPointTool,
60 const TopoDS_Shape& FirstShape,
61 const TopoDS_Shape& SecondShape,
62 const Handle(Geom_Plane)& aPlane)
66 SetFirstShape(FirstShape);
67 SetSecondShape(SecondShape);
69 myPosition = aPlane->Pln().Location();
72 //=======================================================================
75 //=======================================================================
76 void PrsDim_MidPointRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
77 const Handle(Prs3d_Presentation)& aprs,
78 const Standard_Integer)
80 if (myTool.ShapeType() == TopAbs_VERTEX)
83 Standard_Boolean isonplane;
84 if ( PrsDim::ComputeGeometry(TopoDS::Vertex(myTool),pp,myPlane,isonplane) )
86 if ( !isonplane ) ComputeProjVertexPresentation(aprs,TopoDS::Vertex(myTool),pp);
92 if ( myAutomaticPosition ) myPosition = myMidPoint;
94 switch (myFShape.ShapeType())
98 ComputeFaceFromPnt(aprs, Standard_True);
103 ComputeEdgeFromPnt(aprs, Standard_True);
108 ComputeVertexFromPnt(aprs, Standard_True);
115 switch (mySShape.ShapeType())
119 ComputeFaceFromPnt(aprs, Standard_False);
124 ComputeEdgeFromPnt(aprs, Standard_False);
129 ComputeVertexFromPnt(aprs, Standard_False);
137 //=======================================================================
138 //function : ComputeSelection
140 //=======================================================================
141 void PrsDim_MidPointRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSel,
142 const Standard_Integer)
144 Handle(Select3D_SensitiveSegment) seg;
145 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
147 if ( !myMidPoint.IsEqual(myFAttach,Precision::Confusion()) )
149 // segment from mid point to the first geometry
150 seg = new Select3D_SensitiveSegment(own,myFAttach,myMidPoint);
152 // segment from mid point to the second geometry
153 seg = new Select3D_SensitiveSegment(own,mySAttach,myMidPoint);
156 if ( !myMidPoint.IsEqual(myPosition,Precision::Confusion()) )
158 // segment from mid point to the text position
159 seg = new Select3D_SensitiveSegment(own,myMidPoint,myPosition);
163 // center of the symmetry - circle around the MidPoint
164 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
165 ax.SetLocation(myMidPoint);
166 Standard_Real rad = myFAttach.Distance(myMidPoint)/20.0;
167 gp_Circ aCircleM (ax,rad);
168 Handle(Geom_Curve) thecir = new Geom_Circle(aCircleM);
169 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecir);
172 Handle(Geom_Curve) curv;
174 Standard_Boolean isInfinite,isOnPlane;
175 Handle(Geom_Curve) extCurv;
177 // segment on first curve
178 if ( myFShape.ShapeType() == TopAbs_EDGE )
180 TopoDS_Edge E = TopoDS::Edge(myFShape);
181 if ( !PrsDim::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
182 if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
185 seg = new Select3D_SensitiveSegment(own,myFirstPnt1,myFirstPnt2);
188 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
191 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
192 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFirstPnt1);
193 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),myFirstPnt2);
194 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
196 scurv = new Select3D_SensitiveCurve(own, thecu);
199 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
201 // segment on ellipse
202 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
203 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFirstPnt1);
204 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),myFirstPnt2);
205 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
207 scurv = new Select3D_SensitiveCurve(own, thecu);
212 // segment on second curve
213 if ( mySShape.ShapeType() == TopAbs_EDGE )
215 TopoDS_Edge E = TopoDS::Edge(mySShape);
216 if ( !PrsDim::ComputeGeometry(E,curv,firstp,lastp,extCurv,isInfinite,isOnPlane,myPlane) ) return;
217 if ( curv->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of line
220 seg = new Select3D_SensitiveSegment(own,mySecondPnt1,mySecondPnt2);
223 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Circle)) ) // case of circle
226 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv);
227 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),mySecondPnt1);
228 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySecondPnt2);
229 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
231 scurv = new Select3D_SensitiveCurve(own, thecu);
234 else if ( curv->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipse
236 // segment on ellipse
237 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv);
238 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),mySecondPnt1);
239 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySecondPnt2);
240 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
242 scurv = new Select3D_SensitiveCurve(own, thecu);
248 //=======================================================================
249 //function : ComputeFaceFromPnt
251 //=======================================================================
252 void PrsDim_MidPointRelation::ComputeFaceFromPnt(const Handle(Prs3d_Presentation)&,
253 const Standard_Boolean /*first*/)
257 //=======================================================================
258 //function : ComputeEdgeFromPnt
260 //=======================================================================
261 void PrsDim_MidPointRelation::ComputeEdgeFromPnt(const Handle(Prs3d_Presentation)& aprs,
262 const Standard_Boolean first)
265 if ( first ) E = TopoDS::Edge(myFShape);
266 else E = TopoDS::Edge(mySShape);
268 Handle(Geom_Curve) geom;
270 Handle(Geom_Curve) extCurv;
271 Standard_Boolean isInfinite,isOnPlane;
272 if ( !PrsDim::ComputeGeometry(E, geom, ptat1, ptat2, extCurv, isInfinite, isOnPlane, myPlane) ) return;
274 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
276 if ( geom->IsInstance(STANDARD_TYPE(Geom_Line)) )
278 if ( !isInfinite ) ComputePointsOnLine(ptat1,ptat2,first);
281 const gp_Lin& line = Handle(Geom_Line)::DownCast (geom)->Lin();
282 ComputePointsOnLine(line,first);
284 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
285 myFAttach,myFirstPnt1,myFirstPnt2,first);
286 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,
287 mySAttach,mySecondPnt1,mySecondPnt2,first);
289 else if ( geom->IsInstance(STANDARD_TYPE(Geom_Circle)) )
291 Handle(Geom_Circle) geom_cir (Handle(Geom_Circle)::DownCast (geom));
292 gp_Circ circ (geom_cir->Circ());
293 ComputePointsOnCirc(circ,ptat1,ptat2,first);
294 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
295 myFAttach,myFirstPnt1,myFirstPnt2,first);
296 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,circ,myMidPoint,myPosition,
297 mySAttach,mySecondPnt1,mySecondPnt2,first);
299 else if ( geom->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
301 Handle(Geom_Ellipse) geom_ell (Handle(Geom_Ellipse)::DownCast (geom));
302 gp_Elips elips (geom_ell->Elips());
303 ComputePointsOnElips(elips,ptat1,ptat2,first);
304 if ( first ) DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
305 myFAttach,myFirstPnt1,myFirstPnt2,first);
306 else DsgPrs_MidPointPresentation::Add(aprs,myDrawer,elips,myMidPoint,myPosition,
307 mySAttach,mySecondPnt1,mySecondPnt2,first);
311 // projection on myPlane
312 if ( !isOnPlane ) ComputeProjEdgePresentation(aprs,E,geom,ptat1,ptat2);
315 //=======================================================================
316 //function : ComputeVertexFromPnt
318 //=======================================================================
319 void PrsDim_MidPointRelation::ComputeVertexFromPnt(const Handle(Prs3d_Presentation)& aprs,
320 const Standard_Boolean first)
322 gp_Ax2 ax = myPlane->Pln().Position().Ax2();
325 Standard_Boolean isOnPlane;
326 TopoDS_Vertex V = TopoDS::Vertex(myFShape);
327 PrsDim::ComputeGeometry(V, myFAttach, myPlane, isOnPlane);
328 DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,myFAttach,first);
329 if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,myFAttach);
333 Standard_Boolean isOnPlane;
334 TopoDS_Vertex V = TopoDS::Vertex(mySShape);
335 PrsDim::ComputeGeometry(V, mySAttach, myPlane, isOnPlane);
336 DsgPrs_MidPointPresentation::Add(aprs,myDrawer,ax,myMidPoint,myPosition,mySAttach,first);
337 if ( !isOnPlane ) ComputeProjVertexPresentation(aprs,V,mySAttach);
341 //=======================================================================
342 //function : ComputePointsOnLine
344 //=======================================================================
345 void PrsDim_MidPointRelation::ComputePointsOnLine(const gp_Lin& aLin,
346 const Standard_Boolean first)
348 Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
349 gp_Pnt anAttach = ElCLib::Value(ppar,aLin);
351 Standard_Real dist = anAttach.Distance(myMidPoint)/10.0;
352 if ( dist < Precision::Confusion() ) dist = 10.0;
354 Standard_Real fpar = ppar + dist;
355 Standard_Real spar = ppar - dist;
357 gp_Pnt aPnt1 = ElCLib::Value(fpar,aLin);
358 gp_Pnt aPnt2 = ElCLib::Value(spar,aLin);
362 myFAttach = anAttach;
368 mySAttach = anAttach;
369 mySecondPnt1 = aPnt1;
370 mySecondPnt2 = aPnt2;
374 //=======================================================================
375 //function : ComputePointsOnLine
377 //=======================================================================
378 void PrsDim_MidPointRelation::ComputePointsOnLine(const gp_Pnt& pnt1, const gp_Pnt& pnt2,
379 const Standard_Boolean first)
381 gp_Vec aVec (pnt1,pnt2);
382 gp_Lin aLin (pnt1,gp_Dir(aVec));
384 Standard_Real fpar = ElCLib::Parameter(aLin,pnt1);
385 Standard_Real spar = ElCLib::Parameter(aLin,pnt2);
386 Standard_Real ppar = ElCLib::Parameter(aLin,myMidPoint);
388 gp_Pnt aProjPnt = ElCLib::Value(ppar,aLin);
389 Standard_Real dist = myMidPoint.Distance(aProjPnt);
390 Standard_Real ll = pnt1.Distance(pnt2);
391 Standard_Real segm = Min(dist,ll)*0.75;
392 if ( dist < Precision::Confusion() ) segm = ll*0.75;
394 gp_Pnt anAttach,aPnt1,aPnt2;
400 aVecTr = gp_Vec(pnt2,pnt1);
402 aPnt1 = aProjPnt.Translated(aVecTr*segm);
404 else if ( ppar >= spar )
407 aVecTr = gp_Vec(pnt1,pnt2);
409 aPnt2 = aProjPnt.Translated(aVecTr*segm);
413 Standard_Real dp1 = aProjPnt.Distance(pnt1);
414 Standard_Real dp2 = aProjPnt.Distance(pnt2);
416 segm = Min(dist,dp1)*0.75;
417 aVecTr = gp_Vec(aProjPnt,pnt1);
419 aPnt1 = aProjPnt.Translated(aVecTr*segm);
421 segm = Min(dist,dp2)*0.75;
422 aVecTr = gp_Vec(aProjPnt,pnt2);
424 aPnt2 = aProjPnt.Translated(aVecTr*segm);
429 myFAttach = anAttach;
435 mySAttach = anAttach;
436 mySecondPnt1 = aPnt1;
437 mySecondPnt2 = aPnt2;
441 //=======================================================================
442 //function : ComputePointsOnCirc
444 //=======================================================================
445 void PrsDim_MidPointRelation::ComputePointsOnCirc(const gp_Circ& aCirc,
446 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
447 const Standard_Boolean first)
449 gp_Pnt curpos = myMidPoint;
451 // Case of confusion between the current position and the center
452 // of the circle -> we move the current position
453 Standard_Real confusion (Precision::Confusion());
454 gp_Pnt aCenter = aCirc.Location();
455 if ( aCenter.Distance(curpos) <= confusion )
457 gp_Vec vprec(aCenter, pnt1);
459 curpos.Translate(vprec*1e-5);
462 Standard_Real pcurpos = ElCLib::Parameter(aCirc,curpos);
464 Standard_Real rad = M_PI / 5.0;
470 if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
472 pFPnt = pcurpos - rad;
473 pSPnt = pcurpos + rad;
477 Standard_Real pFAttach = ElCLib::Parameter(aCirc,pnt1);
478 Standard_Real pSAttach = ElCLib::Parameter(aCirc,pnt2);
480 Standard_Real pSAttachM = pSAttach;
481 Standard_Real deltap = pSAttachM - pFAttach;
485 pSAttachM += 2 * M_PI;
487 pSAttachM -= pFAttach;
489 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
491 Standard_Real pcurpos1 = pcurpos;
492 // define where curpos lays
493 if ( pcurpos1 < pFAttach )
495 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
496 if ( pcurpos1 > pSAttachM ) // out
498 segm = Min(rad,deltap*0.75);
499 if ( pcurpos1 > pmiddleout )
503 pSPnt = pFAttach + segm;
508 pFPnt = pSAttach - segm;
514 Standard_Real dp1 = pcurpos1 - pFAttach;
515 Standard_Real dp2 = pSAttachM - pcurpos1;
517 segm = Min(rad,dp1*0.75);
518 pFPnt = pcurpos - segm;
520 segm = Min(rad,dp2*0.75);
521 pSPnt = pcurpos + segm;
524 else if ( pcurpos1 > (pFAttach + deltap) ) // out
526 pcurpos1 -= pFAttach;
527 segm = Min(rad,deltap*0.75);
528 if ( pcurpos1 > pmiddleout )
532 pSPnt = pFAttach + segm;
537 pFPnt = pSAttach - segm;
543 Standard_Real dp1 = pcurpos1 - pFAttach;
544 Standard_Real dp2 = pSAttach - pcurpos1;
546 segm = Min(rad,dp1*0.75);
547 pFPnt = pcurpos - segm;
549 segm = Min(rad,dp2*0.75);
550 pSPnt = pcurpos + segm;
556 myFAttach = ElCLib::Value(pcurpos,aCirc);
557 myFirstPnt1 = ElCLib::Value(pFPnt,aCirc);
558 myFirstPnt2 = ElCLib::Value(pSPnt,aCirc);
562 mySAttach = ElCLib::Value(pcurpos,aCirc);
563 mySecondPnt1 = ElCLib::Value(pFPnt,aCirc);
564 mySecondPnt2 = ElCLib::Value(pSPnt,aCirc);
568 //=======================================================================
569 //function : ComputePointsOnElips
571 //=======================================================================
572 void PrsDim_MidPointRelation::ComputePointsOnElips(const gp_Elips& anEll,
573 const gp_Pnt& pnt1, const gp_Pnt& pnt2,
574 const Standard_Boolean first)
576 gp_Pnt curpos = myMidPoint;
578 // Case of confusion between the current position and the center
579 // of the circle -> we move the current position
580 Standard_Real confusion (Precision::Confusion());
581 gp_Pnt aCenter = anEll.Location();
582 if ( aCenter.Distance(curpos) <= confusion )
584 gp_Vec vprec(aCenter, pnt1);
586 curpos.Translate(vprec*1e-5);
589 Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
591 Standard_Real rad = M_PI / 5.0;
597 if ( pnt1.IsEqual(pnt2,confusion) ) // full circle
599 pFPnt = pcurpos - rad;
600 pSPnt = pcurpos + rad;
604 Standard_Real pFAttach = ElCLib::Parameter(anEll,pnt1);
605 Standard_Real pSAttach = ElCLib::Parameter(anEll,pnt2);
607 Standard_Real pSAttachM = pSAttach;
608 Standard_Real deltap = pSAttachM - pFAttach;
612 pSAttachM += 2 * M_PI;
614 pSAttachM -= pFAttach;
616 Standard_Real pmiddleout = pSAttachM / 2.0 + M_PI;
618 Standard_Real pcurpos1 = pcurpos;
619 // define where curpos lays
620 if ( pcurpos1 < pFAttach )
622 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
623 if ( pcurpos1 > pSAttachM ) // out
625 segm = Min(rad,deltap*0.75);
626 if ( pcurpos1 > pmiddleout )
630 pSPnt = pFAttach + segm;
635 pFPnt = pSAttach - segm;
641 Standard_Real dp1 = pcurpos1 - pFAttach;
642 Standard_Real dp2 = pSAttachM - pcurpos1;
644 segm = Min(rad,dp1*0.75);
645 pFPnt = pcurpos - segm;
647 segm = Min(rad,dp2*0.75);
648 pSPnt = pcurpos + segm;
651 else if ( pcurpos1 > (pFAttach + deltap) ) // out
653 pcurpos1 -= pFAttach;
654 segm = Min(rad,deltap*0.75);
655 if ( pcurpos1 > pmiddleout )
659 pSPnt = pFAttach + segm;
664 pFPnt = pSAttach - segm;
670 Standard_Real dp1 = pcurpos1 - pFAttach;
671 Standard_Real dp2 = pSAttach - pcurpos1;
673 segm = Min(rad,dp1*0.75);
674 pFPnt = pcurpos - segm;
676 segm = Min(rad,dp2*0.75);
677 pSPnt = pcurpos + segm;
683 myFAttach = ElCLib::Value(pcurpos,anEll);
684 myFirstPnt1 = ElCLib::Value(pFPnt,anEll);
685 myFirstPnt2 = ElCLib::Value(pSPnt,anEll);
689 mySAttach = ElCLib::Value(pcurpos,anEll);
690 mySecondPnt1 = ElCLib::Value(pFPnt,anEll);
691 mySecondPnt2 = ElCLib::Value(pSPnt,anEll);