0027828: Reference documentation of AIS_Trihedron contains invalid information about...
[occt.git] / src / AIS / AIS_DiameterDimension.cxx
1 // Created on: 1996-12-05
2 // Created by: Jacques MINOT/Odile Olivier/Sergey ZARITCHNY
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <AIS_DiameterDimension.hxx>
18
19 #include <AIS.hxx>
20 #include <BRepLib_MakeEdge.hxx>
21 #include <ElCLib.hxx>
22 #include <GeomAPI_IntCS.hxx>
23 #include <Geom_Circle.hxx>
24 #include <Geom_Plane.hxx>
25 #include <gce_MakeDir.hxx>
26 #include <Standard_ProgramError.hxx>
27
28
29 IMPLEMENT_STANDARD_RTTIEXT(AIS_DiameterDimension,AIS_Dimension)
30
31 namespace
32 {
33   static const Standard_ExtCharacter THE_DIAMETER_SYMBOL (0x00D8);
34 }
35
36 //=======================================================================
37 //function : Constructor
38 //purpose  : 
39 //=======================================================================
40 AIS_DiameterDimension::AIS_DiameterDimension (const gp_Circ& theCircle)
41 : AIS_Dimension (AIS_KOD_DIAMETER)
42 {
43   SetMeasuredGeometry (theCircle);
44   SetSpecialSymbol (THE_DIAMETER_SYMBOL);
45   SetDisplaySpecialSymbol (AIS_DSS_Before);
46   SetFlyout (0.0);
47 }
48
49 //=======================================================================
50 //function : Constructor
51 //purpose  : 
52 //=======================================================================
53 AIS_DiameterDimension::AIS_DiameterDimension (const gp_Circ& theCircle,
54                                               const gp_Pln& thePlane)
55 : AIS_Dimension (AIS_KOD_DIAMETER)
56 {
57   SetCustomPlane (thePlane);
58   SetMeasuredGeometry (theCircle);
59   SetSpecialSymbol (THE_DIAMETER_SYMBOL);
60   SetDisplaySpecialSymbol (AIS_DSS_Before);
61   SetFlyout (0.0);
62 }
63
64 //=======================================================================
65 //function : Constructor
66 //purpose  : 
67 //=======================================================================
68 AIS_DiameterDimension::AIS_DiameterDimension (const TopoDS_Shape& theShape)
69 : AIS_Dimension (AIS_KOD_DIAMETER)
70 {
71   SetMeasuredGeometry (theShape);
72   SetSpecialSymbol (THE_DIAMETER_SYMBOL);
73   SetDisplaySpecialSymbol (AIS_DSS_Before);
74   SetFlyout (0.0);
75 }
76
77 //=======================================================================
78 //function : Constructor
79 //purpose  : 
80 //=======================================================================
81 AIS_DiameterDimension::AIS_DiameterDimension (const TopoDS_Shape& theShape,
82                                               const gp_Pln& thePlane)
83 : AIS_Dimension (AIS_KOD_DIAMETER)
84 {
85   SetCustomPlane (thePlane);
86   SetMeasuredGeometry (theShape);
87   SetSpecialSymbol (THE_DIAMETER_SYMBOL);
88   SetDisplaySpecialSymbol (AIS_DSS_Before);
89   SetFlyout (0.0);
90 }
91
92 //=======================================================================
93 //function : AnchorPoint
94 //purpose  : 
95 //=======================================================================
96 gp_Pnt AIS_DiameterDimension::AnchorPoint()
97 {
98   if (!IsValid())
99   {
100     return gp::Origin();
101   }
102
103   return myAnchorPoint;
104 }
105
106 //=======================================================================
107 //function : SetMeasuredGeometry
108 //purpose  : 
109 //=======================================================================
110 void AIS_DiameterDimension::SetMeasuredGeometry (const gp_Circ& theCircle)
111 {
112   myCircle          = theCircle;
113   myGeometryType    = GeometryType_Edge;
114   myShape           = BRepLib_MakeEdge (theCircle);
115   myAnchorPoint     = gp::Origin();
116   myIsGeometryValid = IsValidCircle (myCircle);
117
118   if (myIsGeometryValid && myIsPlaneCustom)
119   {
120     ComputeAnchorPoint();
121   }
122   else if (!myIsPlaneCustom)
123   {
124     ComputePlane();
125     myAnchorPoint = ElCLib::Value (0.0, myCircle);
126   }
127
128   SetToUpdate();
129 }
130
131 //=======================================================================
132 //function : SetMeasuredGeometry
133 //purpose  : 
134 //=======================================================================
135 void AIS_DiameterDimension::SetMeasuredGeometry (const TopoDS_Shape& theShape)
136 {
137   gp_Pnt aDummyPnt (gp::Origin());
138   Standard_Boolean isClosed = Standard_False;
139
140   myGeometryType    = GeometryType_UndefShapes;
141   myShape           = theShape;
142   myAnchorPoint     = gp::Origin();
143   myIsGeometryValid = InitCircularDimension (theShape, myCircle, aDummyPnt, isClosed)
144                       && IsValidCircle (myCircle)
145                       && isClosed;
146
147   if (myIsGeometryValid && myIsPlaneCustom)
148   {
149     ComputeAnchorPoint();
150   }
151   else if (!myIsPlaneCustom)
152   {
153     ComputePlane();
154     myAnchorPoint = ElCLib::Value (0.0, myCircle);
155   }
156
157   SetToUpdate();
158 }
159
160 //=======================================================================
161 //function : CheckPlane
162 //purpose  : 
163 //=======================================================================
164 Standard_Boolean AIS_DiameterDimension::CheckPlane (const gp_Pln& thePlane) const
165 {
166   // Check if the circle center point belongs to plane.
167   if (!thePlane.Contains (myCircle.Location(), Precision::Confusion()))
168   {
169     return Standard_False;
170   }
171
172   return Standard_True;
173 }
174
175 //=======================================================================
176 //function : ComputePlane
177 //purpose  : 
178 //=======================================================================
179 void AIS_DiameterDimension::ComputePlane()
180 {
181   if (!myIsGeometryValid)
182   {
183     return;
184   }
185
186   myPlane = gp_Pln (gp_Ax3 (myCircle.Position()));
187 }
188
189 //=======================================================================
190 //function : ComputeAnchorPoint
191 //purpose  : 
192 //=======================================================================
193 void AIS_DiameterDimension::ComputeAnchorPoint()
194 {
195   // Anchor point is an intersection of dimension plane and circle.
196   Handle(Geom_Circle) aCircle = new Geom_Circle (myCircle);
197   Handle(Geom_Plane) aPlane = new Geom_Plane (myPlane);
198   GeomAPI_IntCS anIntersector (aCircle, aPlane);
199   if (!anIntersector.IsDone())
200   {
201     myIsGeometryValid = Standard_False;
202     return;
203   }
204
205   // The circle lays on the plane.
206   if (anIntersector.NbPoints() != 2)
207   {
208     myAnchorPoint = ElCLib::Value (0.0, myCircle);
209     myIsGeometryValid = Standard_True;
210     return;
211   }
212
213   gp_Pnt aFirstPoint = anIntersector.Point (1);
214   gp_Pnt aSecondPoint = anIntersector.Point (2);
215
216   // Choose one of two intersection points that stands with
217   // positive direction of flyout.
218   // An anchor point is supposed to be the left attachment point.
219   gp_Dir aFirstDir = gce_MakeDir (aFirstPoint, myCircle.Location());
220   gp_Dir aDir = myPlane.Axis().Direction() ^ aFirstDir;
221   myAnchorPoint = (gp_Vec (aDir) * gp_Vec(myCircle.Position().Direction()) > 0.0)
222                   ? aFirstPoint
223                   : aSecondPoint;
224
225 }
226
227 //=======================================================================
228 //function : GetModelUnits
229 //purpose  :
230 //=======================================================================
231 const TCollection_AsciiString& AIS_DiameterDimension::GetModelUnits() const
232 {
233   return myDrawer->DimLengthModelUnits();
234 }
235
236 //=======================================================================
237 //function : GetDisplayUnits
238 //purpose  :
239 //=======================================================================
240 const TCollection_AsciiString& AIS_DiameterDimension::GetDisplayUnits() const
241 {
242   return myDrawer->DimLengthDisplayUnits();
243 }
244
245 //=======================================================================
246 //function : SetModelUnits
247 //purpose  :
248 //=======================================================================
249 void AIS_DiameterDimension::SetModelUnits (const TCollection_AsciiString& theUnits)
250 {
251   myDrawer->SetDimLengthModelUnits (theUnits);
252 }
253
254 //=======================================================================
255 //function : SetDisplayUnits
256 //purpose  :
257 //=======================================================================
258 void AIS_DiameterDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
259 {
260   myDrawer->SetDimLengthDisplayUnits (theUnits);
261 }
262
263 //=======================================================================
264 //function : ComputeValue
265 //purpose  : 
266 //=======================================================================
267 Standard_Real AIS_DiameterDimension::ComputeValue() const
268 {
269   if (!IsValid())
270   {
271     return 0.0;
272   }
273
274   return myCircle.Radius() * 2.0;
275 }
276
277 //=======================================================================
278 //function : Compute
279 //purpose  : 
280 //=======================================================================
281 void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/,
282                                      const Handle(Prs3d_Presentation)& thePresentation, 
283                                      const Standard_Integer theMode)
284 {
285   mySelectionGeom.Clear (theMode);
286
287   if (!IsValid())
288   {
289     return;
290   }
291
292   gp_Pnt aFirstPnt (gp::Origin());
293   gp_Pnt aSecondPnt (gp::Origin());
294   ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
295
296   DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt);
297 }
298
299 //=======================================================================
300 //function : ComputeFlyoutSelection
301 //purpose  : 
302 //=======================================================================
303 void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection,
304                                                     const Handle(SelectMgr_EntityOwner)& theEntityOwner)
305 {
306   if (!IsValid())
307   {
308     return;
309   }
310
311   gp_Pnt aFirstPnt (gp::Origin());
312   gp_Pnt aSecondPnt (gp::Origin());
313   ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
314
315   ComputeLinearFlyouts (theSelection, theEntityOwner, aFirstPnt, aSecondPnt);
316 }
317
318 //=======================================================================
319 //function : ComputeSidePoints
320 //purpose  : 
321 //=======================================================================
322 void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& theCircle,
323                                                gp_Pnt& theFirstPnt,
324                                                gp_Pnt& theSecondPnt)
325 {
326   theFirstPnt = AnchorPoint();
327
328   gp_Vec aRadiusVector (theCircle.Location(), theFirstPnt);
329   theSecondPnt = theCircle.Location().Translated (-aRadiusVector);
330 }
331
332 //=======================================================================
333 //function : IsValidCircle
334 //purpose  : 
335 //=======================================================================
336 Standard_Boolean AIS_DiameterDimension::IsValidCircle (const gp_Circ& theCircle) const
337 {
338   return (theCircle.Radius() * 2.0) > Precision::Confusion();
339 }
340
341 //=======================================================================
342 //function : IsValidAnchor
343 //purpose  : 
344 //=======================================================================
345 Standard_Boolean AIS_DiameterDimension::IsValidAnchor (const gp_Circ& theCircle,
346                                                        const gp_Pnt& theAnchor) const
347 {
348   gp_Pln aCirclePlane (theCircle.Location(), theCircle.Axis().Direction());
349   Standard_Real anAnchorDist = theAnchor.Distance (theCircle.Location());
350   Standard_Real aRadius      = myCircle.Radius();
351
352   return Abs (anAnchorDist - aRadius) > Precision::Confusion()
353       && aCirclePlane.Contains (theAnchor, Precision::Confusion());
354 }
355
356 //=======================================================================
357 //function : GetTextPosition
358 //purpose  : 
359 //=======================================================================
360 const gp_Pnt AIS_DiameterDimension::GetTextPosition() const
361 {
362   if (IsTextPositionCustom())
363   {
364     return myFixedTextPosition;
365   }
366   
367   // Counts text position according to the dimension parameters
368   return GetTextPositionForLinear (myAnchorPoint, myCircle.Location());
369 }
370
371 //=======================================================================
372 //function : GetTextPosition
373 //purpose  : 
374 //=======================================================================
375 void AIS_DiameterDimension::SetTextPosition (const gp_Pnt& theTextPos)
376 {
377   if (!IsValid())
378   {
379     return;
380   }
381
382   myIsTextPositionFixed = Standard_True;
383   myFixedTextPosition = theTextPos;
384
385   SetToUpdate();
386 }