Integration of OCCT 6.5.0 from SVN
[occt.git] / src / AIS / AIS_RadiusDimension.cxx
1 // File:        AIS_RadiusDimension.cxx
2 // Created:     Tue Dec  5 15:09:04 1996
3 // Author:      Jean-Pierre COMBE/Odile Olivier/Serguei Zaritchny
4 // modified     <SZY> 20-feb-98
5 //              <VBU> myFShape could be a wire.
6
7 #define BUC60915        //GG 05/06/01 Enable to compute the requested arrow size
8 //                      if any in all dimensions.
9
10 #include <Standard_NotImplemented.hxx>
11
12 #include <AIS_RadiusDimension.ixx>
13
14 #include <AIS_DimensionOwner.hxx>
15 #include <DsgPrs_RadiusPresentation.hxx>
16 #include <DsgPrs.hxx>
17
18 #include <Geom_Surface.hxx>
19 #include <Geom_Plane.hxx>
20 #include <Geom_Circle.hxx>
21 #include <Geom_Curve.hxx>
22 #include <Geom_TrimmedCurve.hxx>
23 #include <Geom_ToroidalSurface.hxx>
24 #include <Geom_CylindricalSurface.hxx>
25 #include <Geom_SurfaceOfLinearExtrusion.hxx>
26
27 #include <gp_Circ.hxx>
28 #include <gp_Pnt.hxx>
29 #include <gp_Trsf.hxx>
30 #include <ElCLib.hxx>
31 #include <GC_MakeCircle.hxx>
32 #include <gce_MakeLin.hxx>
33 #include <gce_MakeCirc.hxx>
34
35 #include <SelectMgr_EntityOwner.hxx>
36 #include <Select3D_SensitiveSegment.hxx>
37
38 #include <Precision.hxx>
39
40 #include <TopExp_Explorer.hxx>
41 #include <TopAbs_ShapeEnum.hxx>
42 #include <TopoDS.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Wire.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopLoc_Location.hxx>
47 #include <BRep_Tool.hxx>
48 #include <BRepAdaptor_Surface.hxx>
49 #include <BRepAdaptor_Curve.hxx>
50 #include <Adaptor3d_HCurve.hxx>
51
52 #include <Prs3d_AngleAspect.hxx>
53 #include <Prs3d_ArrowAspect.hxx>
54 #include <Prs3d_LengthAspect.hxx>
55 #include <Prs3d_Drawer.hxx>
56
57 #include <TCollection_AsciiString.hxx>
58 #include <TCollection_ExtendedString.hxx>
59
60
61 #include <AIS.hxx>
62 #include <AIS_Drawer.hxx>
63 #include <gce_MakeDir.hxx>
64 #include <Select3D_SensitiveBox.hxx>
65
66
67
68 //======================================================================
69 //function : CircleFromPlanarFace
70 //purpose  : if possible gets circle from planar face
71 //=======================================================================
72 static Standard_Boolean CircleFromPlanarFace (const TopoDS_Shape& aFace,
73                                               Handle(Geom_Curve)& aCurve, 
74                                               gp_Pnt & ptfirst,
75                                               gp_Pnt & ptend)
76 {
77   TopExp_Explorer ExploEd (aFace, TopAbs_EDGE);
78   for ( ; ExploEd.More(); ExploEd.Next())
79     {
80       TopoDS_Edge curedge =  TopoDS::Edge (ExploEd.Current());
81       if (AIS::ComputeGeometry (curedge, aCurve, ptfirst, ptend))
82         if (aCurve->IsInstance (STANDARD_TYPE(Geom_Circle)) && 
83             !Handle(Geom_Circle)::DownCast(aCurve).IsNull())
84           return Standard_True;
85     }
86   return Standard_False;
87 }
88
89
90 //=======================================================================
91 //function : Constructor
92 //purpose  : 
93 //=======================================================================
94 AIS_RadiusDimension::AIS_RadiusDimension(const TopoDS_Shape& aShape, 
95                                          const Standard_Real aVal, 
96                                          const TCollection_ExtendedString& aText)
97 :mydrawFromCenter(Standard_True)
98 {
99   myFShape = aShape;
100   myVal = aVal;
101   myText = aText;
102   mySymbolPrs = DsgPrs_AS_FIRSTPT_LASTAR;
103   myAutomaticPosition = Standard_True;
104
105   myArrowSize = myVal / 100.;
106   InitFirstShape();
107 }
108
109 //=======================================================================
110 //function : Constructor
111 //purpose  :(avec position et texte)
112 //=======================================================================
113 AIS_RadiusDimension::AIS_RadiusDimension( const TopoDS_Shape& aShape, 
114                                           const Standard_Real aVal, 
115                                           const TCollection_ExtendedString& aText, 
116                                           const gp_Pnt& aPosition,
117                                           const DsgPrs_ArrowSide aSymbolPrs, 
118                                           const Standard_Real anArrowSize )
119 :mydrawFromCenter(Standard_True)
120 {
121   myFShape = aShape;
122   myVal = aVal;
123   myText = aText;
124   myPosition = aPosition;
125   mySymbolPrs = aSymbolPrs;
126 #ifdef BUC60915
127   SetArrowSize( anArrowSize );
128 #else
129   myArrowSize = anArrowSize;
130 #endif
131   myAutomaticPosition = Standard_False;
132   InitFirstShape();
133 }
134
135 //=======================================================================
136 //function : InitFirstShape
137 //purpose  : 
138 //=======================================================================
139 void AIS_RadiusDimension::InitFirstShape()
140 {
141   if (myFShape.ShapeType() == TopAbs_FACE)
142     {
143       BRepAdaptor_Surface surfAlgo( TopoDS::Face( myFShape ) );
144       Standard_Real uFirst, uLast, vFirst, vLast;
145       uFirst = surfAlgo.FirstUParameter();
146       uLast = surfAlgo.LastUParameter();
147       vFirst = surfAlgo.FirstVParameter();
148       vLast = surfAlgo.LastVParameter();
149       Standard_Real uMoy = (uFirst + uLast)/2;
150       Standard_Real vMoy = (vFirst + vLast)/2;
151       Handle( Geom_Surface ) surf = surfAlgo.Surface().Surface();
152       surf = Handle( Geom_Surface )::DownCast( surf->Transformed( surfAlgo.Trsf() ) );
153       Handle( Geom_Curve ) aCurve;
154
155       if (surf->DynamicType() == STANDARD_TYPE(Geom_ToroidalSurface))
156         {
157           aCurve = surf->UIso( uMoy );
158           uFirst = vFirst;
159           uLast = vLast;
160         }
161       else if (surf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) 
162         {
163           Handle( Adaptor3d_HCurve ) BasisCurve = surfAlgo.BasisCurve();
164           if ( BasisCurve->GetType() == GeomAbs_Circle )
165             aCurve = surf->VIso( vMoy );
166           else return;
167         }
168       else if (surf->DynamicType() == STANDARD_TYPE(Geom_Plane)) 
169         {
170           gp_Pnt FirstPnt, LastPnt;
171           if (CircleFromPlanarFace (TopoDS::Face(myFShape), aCurve, FirstPnt, LastPnt))
172 //        if (CircleFromPlanarFace (myFShape, aCurve, FirstPnt, LastPnt))
173             {
174               uFirst = ElCLib::Parameter ((Handle(Geom_Circle)::DownCast( aCurve ))->Circ(), FirstPnt);
175               uLast  = ElCLib::Parameter ((Handle(Geom_Circle)::DownCast( aCurve ))->Circ(), LastPnt);
176             }
177           else return;
178         }
179       else
180         aCurve = surf->VIso( vMoy );
181       
182       if (aCurve->DynamicType() == STANDARD_TYPE(Geom_Circle))
183         myCircle = (Handle( Geom_Circle )::DownCast( aCurve ))->Circ();
184       else if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
185         Handle(Geom_TrimmedCurve) tCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve); 
186         aCurve = tCurve->BasisCurve();
187         uFirst = tCurve->FirstParameter();
188         uLast  = tCurve->LastParameter();
189         if (aCurve->DynamicType() == STANDARD_TYPE(Geom_Circle))
190           myCircle = Handle(Geom_Circle)::DownCast(aCurve)->Circ();//gp_Circ
191         else return;
192       }
193       else if (aCurve->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve)) {
194         gp_Pnt P1,P2,P3;
195         aCurve->D0(uFirst,P1);
196         aCurve->D0((uFirst+uLast)/2,P2);
197         aCurve->D0(uLast,P3);
198         gce_MakeCirc MakeCirc = gce_MakeCirc(P1,P2,P3);
199         myCircle = MakeCirc.Value();
200         uFirst = ElCLib::Parameter(myCircle,P1);
201         uLast = ElCLib::Parameter(myCircle,P2);
202       }
203
204       myFirstPar = uFirst;
205       myLastPar  = uLast;
206     } // TopAbs_FACE
207
208   else // it is edge or a wire
209     {
210       TopoDS_Edge anEdge;
211       if (myFShape.ShapeType() == TopAbs_WIRE)  {
212         TopExp_Explorer exp (myFShape,TopAbs_EDGE);
213         if (exp.More())  anEdge = TopoDS::Edge (exp.Current());
214       }
215       else {
216         if ( myFShape.ShapeType() == TopAbs_EDGE) { 
217           anEdge = TopoDS::Edge (myFShape);
218           BRepAdaptor_Curve AdaptedCurve (anEdge);
219           if (!AdaptedCurve.GetType() == GeomAbs_Circle) return;
220           
221           myCircle = AdaptedCurve.Circle();
222           myFirstPar = AdaptedCurve.FirstParameter();
223           myLastPar = AdaptedCurve.LastParameter();
224         }
225 #ifdef DEB
226         else {
227           cout << "AIS_RadiusDimension::InitFirstShape ==> myFShape.ShapeType() == " << myFShape.ShapeType()  << endl;
228         }
229 #endif
230       }
231     } 
232
233   myCenter = myCircle.Location();
234   myCircle.SetRadius(myVal);
235   while (myFirstPar > 2*PI) myFirstPar -= 2*PI;
236   while (myFirstPar < 0.0 ) myFirstPar += 2*PI;
237   while (myLastPar  > 2*PI) myLastPar  -= 2*PI;
238   while (myLastPar  < 0.0 ) myLastPar  += 2*PI;
239   myPlane = new Geom_Plane(gp_Pln(gp_Ax3(myCircle.Position())));
240   myFirstLine = gce_MakeLin( myCenter, ElCLib::Value( myFirstPar, myCircle ) );
241   myLastLine  = gce_MakeLin( myCenter, ElCLib::Value( myLastPar, myCircle ) );
242 }
243
244 //=======================================================================
245 //function : SetFirstShape
246 //purpose  : 
247 //=======================================================================
248 void AIS_RadiusDimension::SetFirstShape( const TopoDS_Shape& aFShape )
249 {
250   myFShape = aFShape;
251   InitFirstShape();
252 }
253
254 //=======================================================================
255 //function : Compute
256 //purpose  : 
257 //=======================================================================
258 void AIS_RadiusDimension::Compute(const Handle(PrsMgr_PresentationManager3d)& /*aPresentationManager*/,
259                                   const Handle(Prs3d_Presentation)& aPresentation, 
260                                   const Standard_Integer /*aMode*/)
261 {
262   aPresentation->Clear();
263
264   ComputeRadius( aPresentation );
265 }
266
267 //=======================================================================
268 //function : Compute
269 //purpose  :  to avoid warning
270 //=======================================================================
271 void AIS_RadiusDimension::Compute(const Handle(Prs3d_Projector)& aProjector, 
272                                   const Handle(Prs3d_Presentation)& aPresentation)
273 {
274 // Standard_NotImplemented::Raise("AIS_RadiusDimension::Compute(const Handle(Prs3d_Projector)& aProjector,const Handle(Prs3d_Presentation)& aPresentation)");
275  PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
276 }
277
278 //=======================================================================
279 //function : Compute
280 //purpose  :  to avoid warning
281 //=======================================================================
282 void AIS_RadiusDimension::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager, 
283                                   const Handle(Graphic2d_GraphicObject)& aPresentation, 
284                                   const Standard_Integer aMode)
285 {
286 // Standard_NotImplemented::Raise("AIS_RadiusDimension::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager,const Handle(Graphic2d_GraphicObject)& aPresentation,const Standard_Integer aMode)");
287  PrsMgr_PresentableObject::Compute( aPresentationManager ,aPresentation,aMode) ;
288 }
289
290 //=======================================================================
291 //function : Compute
292 //purpose  : 
293 //=======================================================================
294
295 void AIS_RadiusDimension::Compute(const Handle_Prs3d_Projector& aProjector,
296                                   const Handle_Geom_Transformation& aTransformation,
297                                   const Handle_Prs3d_Presentation& aPresentation)
298 {
299 // Standard_NotImplemented::Raise("AIS_RadiusDimension::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
300  PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
301 }
302
303 //=======================================================================
304 //function : ComputeSelection
305 //purpose  : 
306 //=======================================================================
307 void AIS_RadiusDimension::ComputeSelection( const Handle(SelectMgr_Selection)& aSelection, 
308                                             const Standard_Integer )
309 {
310   gp_Pnt LineOrigin, LineEnd;
311   DsgPrs::ComputeRadiusLine( myCenter, myEndOfArrow, myPosition, mydrawFromCenter,
312                             LineOrigin,LineEnd); 
313   Handle(AIS_DimensionOwner) own = new AIS_DimensionOwner(this,7);
314   own->SetShape(myFShape);
315   Handle( Select3D_SensitiveSegment ) seg = new Select3D_SensitiveSegment( own, LineOrigin, LineEnd );
316   aSelection->Add( seg );
317
318   // Text
319   Standard_Real size(Min(myVal/100.+1.e-6,myArrowSize+1.e-6));
320   Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
321                                                                    myPosition.X(),
322                                                                    myPosition.Y(),
323                                                                    myPosition.Z(),
324                                                                    myPosition.X() + size,
325                                                                    myPosition.Y() + size,
326                                                                    myPosition.Z() + size );
327   aSelection->Add(box);
328 }
329
330 //=======================================================================
331 //function : ComputeRadius
332 //purpose  : 
333 //=======================================================================
334
335 void AIS_RadiusDimension::ComputeRadius( const Handle( Prs3d_Presentation )& aPresentation )
336 {
337    if (myAutomaticPosition)
338      {
339        InitFirstShape();
340        myEndOfArrow = ElCLib::Value( (myFirstPar + myLastPar)/2, myCircle );
341        if(mydrawFromCenter) {
342          myPosition = myCenter;
343        }
344        else 
345          {
346            gp_Vec v1(myCenter, myEndOfArrow);
347            myPosition = myCenter.Translated(v1 * 1.2);
348          }
349        myAutomaticPosition = Standard_True;
350        
351        if (myIsSetBndBox)
352          myPosition = AIS::TranslatePointToBound(myPosition, gce_MakeDir( myCenter, myEndOfArrow ),
353                                                  myBndBox );       
354      }
355    else
356      {
357        //!Automaticposition
358        myPosition = AIS::ProjectPointOnPlane( myPosition, myPlane->Pln() );
359        Standard_Real PosPar = ElCLib::Parameter( myCircle, myPosition );
360        if (!AIS::InDomain(myFirstPar, myLastPar, PosPar))
361          { // not in domain
362            Standard_Real otherpar = PosPar + PI;
363            if (otherpar > 2*PI) otherpar -= 2*PI;
364            if (AIS::InDomain(myFirstPar, myLastPar, otherpar)){
365              PosPar = otherpar;// parameter on circle
366              myEndOfArrow = ElCLib::Value( PosPar, myCircle );
367            }
368            else {
369              Standard_Real Teta1 = Abs( PosPar - myFirstPar ), Teta2 = Abs( PosPar - myLastPar );
370              if (Teta1 > PI)
371                Teta1 = 2.0*PI - Teta1; 
372              if (Teta2 > PI)
373                Teta2 = 2.0*PI - Teta2; 
374              if (Teta1 < Teta2) 
375                {
376                  if(myFirstLine.Contains(myPosition,Precision::Confusion()))
377                    PosPar = myFirstPar;
378                  else
379                    PosPar = myLastPar;
380                }
381              else
382                {
383                  if(myLastLine.Contains(myPosition,Precision::Confusion()))
384                    PosPar = myLastPar; 
385                  else 
386                    PosPar = myFirstPar;
387                }
388              myEndOfArrow = ElCLib::Value( PosPar, myCircle );
389              gp_Lin RadiusLine = gce_MakeLin( myCenter, myEndOfArrow );
390              // project on radius line
391              myPosition = ElCLib::Value( ElCLib::Parameter( RadiusLine, myPosition ), RadiusLine );
392            }
393          }
394        else
395          myEndOfArrow = ElCLib::Value( PosPar, myCircle );
396      }
397    
398    Handle(Prs3d_LengthAspect) la = myDrawer->LengthAspect();
399    Handle(Prs3d_ArrowAspect) arr = la->Arrow1Aspect();
400    // size
401 #ifdef BUC60915
402    if( !myArrowSizeIsDefined ) {
403      myArrowSize = Min(myArrowSize,myVal/5.);
404    }
405    arr->SetLength(myArrowSize);
406 #else
407    if (myVal/5. > myArrowSize) 
408      arr->SetLength(myArrowSize);
409    else 
410      arr->SetLength(myVal/5.);
411 #endif
412    
413    DsgPrs_RadiusPresentation::Add( aPresentation, myDrawer, myText, myPosition,
414                                   myCenter, myEndOfArrow, mySymbolPrs, mydrawFromCenter );
415  }