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