b311480e |
1 | // Created on: 1996-12-05 |
2 | // Created by: Arnaud BOUZY/Odile Olivier |
3 | // Copyright (c) 1996-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
b311480e |
16 | |
787ff240 |
17 | #include <PrsDim_AngleDimension.hxx> |
7fd59977 |
18 | |
787ff240 |
19 | #include <PrsDim.hxx> |
7fd59977 |
20 | #include <BRepBuilderAPI_MakeFace.hxx> |
21 | #include <BRepAdaptor_Curve.hxx> |
22 | #include <BRepAdaptor_Surface.hxx> |
60bf98ae |
23 | #include <BRepLib_MakeVertex.hxx> |
24 | #include <BRep_Tool.hxx> |
7fd59977 |
25 | #include <ElCLib.hxx> |
60bf98ae |
26 | #include <GCPnts_UniformAbscissa.hxx> |
27 | #include <GC_MakeArcOfCircle.hxx> |
a6eb515f |
28 | #include <gce_MakeLin2d.hxx> |
60bf98ae |
29 | #include <gce_MakeLin.hxx> |
30 | #include <gce_MakeCirc.hxx> |
a6eb515f |
31 | #include <gce_MakeCone.hxx> |
fe83e1ea |
32 | #include <gce_MakePln.hxx> |
fe83e1ea |
33 | #include <gce_MakeDir.hxx> |
7fd59977 |
34 | #include <Geom_Circle.hxx> |
60bf98ae |
35 | #include <Geom_TrimmedCurve.hxx> |
7fd59977 |
36 | #include <Geom_ConicalSurface.hxx> |
37 | #include <Geom_SurfaceOfRevolution.hxx> |
7fd59977 |
38 | #include <Geom_OffsetSurface.hxx> |
a6eb515f |
39 | #include <Graphic3d_ArrayOfSegments.hxx> |
a6eb515f |
40 | #include <Graphic3d_Group.hxx> |
a6eb515f |
41 | #include <Graphic3d_ArrayOfPolylines.hxx> |
7fd59977 |
42 | #include <IntAna2d_AnaIntersection.hxx> |
7fd59977 |
43 | #include <ProjLib.hxx> |
a6eb515f |
44 | #include <Prs3d_Root.hxx> |
d7bffd44 |
45 | #include <Prs3d_ShadingAspect.hxx> |
a6eb515f |
46 | #include <PrsMgr_PresentationManager3d.hxx> |
62b6361a |
47 | #include <Select3D_SensitiveGroup.hxx> |
7fd59977 |
48 | #include <Select3D_SensitiveSegment.hxx> |
a6eb515f |
49 | #include <SelectMgr_Selection.hxx> |
af203d54 |
50 | #include <Standard_ProgramError.hxx> |
7fd59977 |
51 | #include <UnitsAPI.hxx> |
ec357c5c |
52 | #include <Geom_Line.hxx> |
53 | #include <Geom_Plane.hxx> |
7fd59977 |
54 | |
787ff240 |
55 | IMPLEMENT_STANDARD_RTTIEXT(PrsDim_AngleDimension, PrsDim_Dimension) |
92efcf78 |
56 | |
d7bffd44 |
57 | namespace |
58 | { |
fe83e1ea |
59 | static const TCollection_ExtendedString THE_EMPTY_LABEL_STRING; |
60 | static const Standard_Real THE_EMPTY_LABEL_WIDTH = 0.0; |
61 | static const Standard_ExtCharacter THE_DEGREE_SYMBOL (0x00B0); |
62 | static const Standard_Real THE_3D_TEXT_MARGIN = 0.1; |
0f0f0c06 |
63 | |
64 | //! Returns true if the given points lie on a same line. |
65 | static Standard_Boolean isSameLine (const gp_Pnt& theFirstPoint, |
66 | const gp_Pnt& theCenterPoint, |
67 | const gp_Pnt& theSecondPoint) |
68 | { |
69 | gp_Vec aVec1 (theFirstPoint, theCenterPoint); |
70 | gp_Vec aVec2 (theCenterPoint, theSecondPoint); |
71 | |
72 | return aVec1.IsParallel (aVec2, Precision::Angular()); |
73 | } |
a3f6f591 |
74 | } |
d7bffd44 |
75 | |
7fd59977 |
76 | //======================================================================= |
77 | //function : Constructor |
60bf98ae |
78 | //purpose : |
7fd59977 |
79 | //======================================================================= |
787ff240 |
80 | PrsDim_AngleDimension::PrsDim_AngleDimension (const TopoDS_Edge& theFirstEdge, |
81 | const TopoDS_Edge& theSecondEdge) |
82 | : PrsDim_Dimension (PrsDim_KOD_PLANEANGLE) |
7fd59977 |
83 | { |
60bf98ae |
84 | Init(); |
85 | SetMeasuredGeometry (theFirstEdge, theSecondEdge); |
7fd59977 |
86 | } |
87 | |
7fd59977 |
88 | //======================================================================= |
89 | //function : Constructor |
60bf98ae |
90 | //purpose : |
7fd59977 |
91 | //======================================================================= |
787ff240 |
92 | PrsDim_AngleDimension::PrsDim_AngleDimension (const gp_Pnt& theFirstPoint, |
93 | const gp_Pnt& theSecondPoint, |
94 | const gp_Pnt& theThirdPoint) |
95 | : PrsDim_Dimension (PrsDim_KOD_PLANEANGLE) |
7fd59977 |
96 | { |
60bf98ae |
97 | Init(); |
98 | SetMeasuredGeometry (theFirstPoint, theSecondPoint, theThirdPoint); |
7fd59977 |
99 | } |
100 | |
101 | //======================================================================= |
102 | //function : Constructor |
60bf98ae |
103 | //purpose : |
7fd59977 |
104 | //======================================================================= |
787ff240 |
105 | PrsDim_AngleDimension::PrsDim_AngleDimension (const TopoDS_Vertex& theFirstVertex, |
106 | const TopoDS_Vertex& theSecondVertex, |
107 | const TopoDS_Vertex& theThirdVertex) |
108 | : PrsDim_Dimension (PrsDim_KOD_PLANEANGLE) |
7fd59977 |
109 | { |
60bf98ae |
110 | Init(); |
111 | SetMeasuredGeometry (theFirstVertex, theSecondVertex, theThirdVertex); |
7fd59977 |
112 | } |
113 | |
7fd59977 |
114 | //======================================================================= |
a6eb515f |
115 | //function : Constructor |
60bf98ae |
116 | //purpose : |
7fd59977 |
117 | //======================================================================= |
787ff240 |
118 | PrsDim_AngleDimension::PrsDim_AngleDimension (const TopoDS_Face& theCone) |
119 | : PrsDim_Dimension (PrsDim_KOD_PLANEANGLE) |
7fd59977 |
120 | { |
60bf98ae |
121 | Init(); |
122 | SetMeasuredGeometry (theCone); |
7fd59977 |
123 | } |
124 | |
125 | //======================================================================= |
a6eb515f |
126 | //function : Constructor |
60bf98ae |
127 | //purpose : |
7fd59977 |
128 | //======================================================================= |
787ff240 |
129 | PrsDim_AngleDimension::PrsDim_AngleDimension (const TopoDS_Face& theFirstFace, |
130 | const TopoDS_Face& theSecondFace) |
131 | : PrsDim_Dimension (PrsDim_KOD_PLANEANGLE) |
7fd59977 |
132 | { |
60bf98ae |
133 | Init(); |
134 | SetMeasuredGeometry (theFirstFace, theSecondFace); |
7fd59977 |
135 | } |
136 | |
7fd59977 |
137 | //======================================================================= |
60bf98ae |
138 | //function : Constructor |
7fd59977 |
139 | //purpose : |
140 | //======================================================================= |
787ff240 |
141 | PrsDim_AngleDimension::PrsDim_AngleDimension (const TopoDS_Face& theFirstFace, |
142 | const TopoDS_Face& theSecondFace, |
143 | const gp_Pnt& thePoint) |
144 | : PrsDim_Dimension (PrsDim_KOD_PLANEANGLE) |
7fd59977 |
145 | { |
60bf98ae |
146 | Init(); |
147 | SetMeasuredGeometry (theFirstFace, theSecondFace, thePoint); |
7fd59977 |
148 | } |
149 | |
7fd59977 |
150 | //======================================================================= |
60bf98ae |
151 | //function : SetMeasuredGeometry |
152 | //purpose : |
7fd59977 |
153 | //======================================================================= |
787ff240 |
154 | void PrsDim_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge, |
155 | const TopoDS_Edge& theSecondEdge) |
7fd59977 |
156 | { |
60bf98ae |
157 | gp_Pln aComputedPlane; |
158 | |
91b16a64 |
159 | myFirstShape = theFirstEdge; |
160 | mySecondShape = theSecondEdge; |
161 | myThirdShape = TopoDS_Shape(); |
162 | myGeometryType = GeometryType_Edges; |
163 | myIsGeometryValid = InitTwoEdgesAngle (aComputedPlane); |
60bf98ae |
164 | |
91b16a64 |
165 | if (myIsGeometryValid && !myIsPlaneCustom) |
60bf98ae |
166 | { |
4d147bf2 |
167 | myPlane = aComputedPlane; |
60bf98ae |
168 | } |
169 | |
60bf98ae |
170 | SetToUpdate(); |
7fd59977 |
171 | } |
172 | |
173 | //======================================================================= |
60bf98ae |
174 | //function : SetMeasuredGeometry |
175 | //purpose : |
7fd59977 |
176 | //======================================================================= |
787ff240 |
177 | void PrsDim_AngleDimension::SetMeasuredGeometry (const gp_Pnt& theFirstPoint, |
178 | const gp_Pnt& theSecondPoint, |
179 | const gp_Pnt& theThirdPoint) |
7fd59977 |
180 | { |
60bf98ae |
181 | myFirstPoint = theFirstPoint; |
182 | myCenterPoint = theSecondPoint; |
183 | mySecondPoint = theThirdPoint; |
184 | myFirstShape = BRepLib_MakeVertex (myFirstPoint); |
185 | mySecondShape = BRepLib_MakeVertex (myCenterPoint); |
186 | myThirdShape = BRepLib_MakeVertex (mySecondPoint); |
187 | myGeometryType = GeometryType_Points; |
91b16a64 |
188 | myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
7fd59977 |
189 | |
0f0f0c06 |
190 | Standard_Boolean anIsSameLine = isSameLine (myFirstPoint, myCenterPoint, mySecondPoint); |
191 | if (myIsGeometryValid && !myIsPlaneCustom && !anIsSameLine) |
a6eb515f |
192 | { |
60bf98ae |
193 | ComputePlane(); |
194 | } |
a6eb515f |
195 | |
60bf98ae |
196 | SetToUpdate(); |
197 | } |
a6eb515f |
198 | |
60bf98ae |
199 | //======================================================================= |
200 | //function : SetMeasuredGeometry |
201 | //purpose : |
202 | //======================================================================= |
787ff240 |
203 | void PrsDim_AngleDimension::SetMeasuredGeometry (const TopoDS_Vertex& theFirstVertex, |
204 | const TopoDS_Vertex& theSecondVertex, |
205 | const TopoDS_Vertex& theThirdVertex) |
60bf98ae |
206 | { |
91b16a64 |
207 | myFirstShape = theFirstVertex; |
208 | mySecondShape = theSecondVertex; |
209 | myThirdShape = theThirdVertex; |
210 | myFirstPoint = BRep_Tool::Pnt (theFirstVertex); |
211 | myCenterPoint = BRep_Tool::Pnt (theSecondVertex); |
212 | mySecondPoint = BRep_Tool::Pnt (theThirdVertex); |
213 | myGeometryType = GeometryType_Points; |
214 | myIsGeometryValid = IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
215 | |
0f0f0c06 |
216 | Standard_Boolean anIsSameLine = isSameLine (myFirstPoint, myCenterPoint, mySecondPoint); |
217 | if (myIsGeometryValid && !myIsPlaneCustom && !anIsSameLine) |
a6eb515f |
218 | { |
60bf98ae |
219 | ComputePlane(); |
7fd59977 |
220 | } |
7fd59977 |
221 | |
60bf98ae |
222 | SetToUpdate(); |
223 | } |
7fd59977 |
224 | |
60bf98ae |
225 | //======================================================================= |
226 | //function : SetMeasuredGeometry |
227 | //purpose : |
228 | //======================================================================= |
787ff240 |
229 | void PrsDim_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theCone) |
60bf98ae |
230 | { |
91b16a64 |
231 | myFirstShape = theCone; |
232 | mySecondShape = TopoDS_Shape(); |
233 | myThirdShape = TopoDS_Shape(); |
234 | myGeometryType = GeometryType_Face; |
235 | myIsGeometryValid = InitConeAngle(); |
7fd59977 |
236 | |
91b16a64 |
237 | if (myIsGeometryValid && !myIsPlaneCustom) |
a6eb515f |
238 | { |
60bf98ae |
239 | ComputePlane(); |
a6eb515f |
240 | } |
7fd59977 |
241 | |
60bf98ae |
242 | SetToUpdate(); |
7fd59977 |
243 | } |
244 | |
245 | //======================================================================= |
60bf98ae |
246 | //function : SetMeasuredGeometry |
247 | //purpose : |
7fd59977 |
248 | //======================================================================= |
787ff240 |
249 | void PrsDim_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace, |
250 | const TopoDS_Face& theSecondFace) |
7fd59977 |
251 | { |
91b16a64 |
252 | myFirstShape = theFirstFace; |
253 | mySecondShape = theSecondFace; |
254 | myThirdShape = TopoDS_Shape(); |
255 | myGeometryType = GeometryType_Faces; |
256 | myIsGeometryValid = InitTwoFacesAngle(); |
a6eb515f |
257 | |
91b16a64 |
258 | if (myIsGeometryValid && !myIsPlaneCustom) |
a6eb515f |
259 | { |
60bf98ae |
260 | ComputePlane(); |
7fd59977 |
261 | } |
60bf98ae |
262 | |
60bf98ae |
263 | SetToUpdate(); |
7fd59977 |
264 | } |
265 | |
7fd59977 |
266 | //======================================================================= |
60bf98ae |
267 | //function : SetMeasuredGeometry |
7fd59977 |
268 | //purpose : |
269 | //======================================================================= |
787ff240 |
270 | void PrsDim_AngleDimension::SetMeasuredGeometry (const TopoDS_Face& theFirstFace, |
271 | const TopoDS_Face& theSecondFace, |
272 | const gp_Pnt& thePoint) |
7fd59977 |
273 | { |
91b16a64 |
274 | myFirstShape = theFirstFace; |
275 | mySecondShape = theSecondFace; |
276 | myThirdShape = TopoDS_Shape(); |
277 | myGeometryType = GeometryType_Faces; |
278 | myIsGeometryValid = InitTwoFacesAngle (thePoint); |
60bf98ae |
279 | |
91b16a64 |
280 | if (myIsGeometryValid && !myIsPlaneCustom) |
60bf98ae |
281 | { |
282 | ComputePlane(); |
283 | } |
284 | |
60bf98ae |
285 | SetToUpdate(); |
7fd59977 |
286 | } |
287 | |
288 | //======================================================================= |
60bf98ae |
289 | //function : Init |
7fd59977 |
290 | //purpose : |
291 | //======================================================================= |
787ff240 |
292 | void PrsDim_AngleDimension::Init() |
7fd59977 |
293 | { |
787ff240 |
294 | SetType (PrsDim_TypeOfAngle_Interior); |
295 | SetArrowsVisibility (PrsDim_TypeOfAngleArrowVisibility_Both); |
60bf98ae |
296 | SetSpecialSymbol (THE_DEGREE_SYMBOL); |
787ff240 |
297 | SetDisplaySpecialSymbol (PrsDim_DisplaySpecialSymbol_After); |
60bf98ae |
298 | SetFlyout (15.0); |
7fd59977 |
299 | } |
300 | |
7fd59977 |
301 | //======================================================================= |
60bf98ae |
302 | //function: GetCenterOnArc |
303 | //purpose : |
7fd59977 |
304 | //======================================================================= |
787ff240 |
305 | gp_Pnt PrsDim_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach, |
306 | const gp_Pnt& theSecondAttach, |
307 | const gp_Pnt& theCenter) const |
7fd59977 |
308 | { |
60bf98ae |
309 | // construct plane where the circle and the arc are located |
310 | gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter); |
311 | if (!aConstructPlane.IsDone()) |
a6eb515f |
312 | { |
60bf98ae |
313 | return gp::Origin(); |
7fd59977 |
314 | } |
60bf98ae |
315 | |
316 | gp_Pln aPlane = aConstructPlane.Value(); |
ee905e84 |
317 | // to have an exterior angle presentation, a plane for further constructed circle should be reversed |
787ff240 |
318 | if (myType == PrsDim_TypeOfAngle_Exterior) |
ee905e84 |
319 | { |
320 | gp_Ax1 anAxis = aPlane.Axis(); |
321 | gp_Dir aDir = anAxis.Direction(); |
322 | aDir.Reverse(); |
323 | aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir)); |
324 | } |
7fd59977 |
325 | |
60bf98ae |
326 | Standard_Real aRadius = theFirstAttach.Distance (theCenter); |
7fd59977 |
327 | |
60bf98ae |
328 | // construct circle forming the arc |
329 | gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius); |
330 | if (!aConstructCircle.IsDone()) |
a6eb515f |
331 | { |
60bf98ae |
332 | return gp::Origin(); |
7fd59977 |
333 | } |
334 | |
60bf98ae |
335 | gp_Circ aCircle = aConstructCircle.Value(); |
336 | |
337 | // compute angle parameters of arc end-points on circle |
338 | Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach); |
339 | Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach); |
340 | ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); |
7fd59977 |
341 | |
60bf98ae |
342 | return ElCLib::Value ((aParamBeg + aParamEnd) * 0.5, aCircle); |
343 | } |
344 | |
4d147bf2 |
345 | //======================================================================= |
346 | //function : GetNormalForMinAngle |
347 | //purpose : |
348 | //======================================================================= |
787ff240 |
349 | gp_Dir PrsDim_AngleDimension::GetNormalForMinAngle() const |
4d147bf2 |
350 | { |
351 | const gp_Dir& aNormal = myPlane.Axis().Direction(); |
352 | gp_Dir aFirst (gp_Vec (myCenterPoint, myFirstPoint) ); |
353 | gp_Dir aSecond (gp_Vec (myCenterPoint, mySecondPoint) ); |
354 | |
355 | return aFirst.AngleWithRef (aSecond, aNormal) < 0.0 |
356 | ? aNormal.Reversed() |
357 | : aNormal; |
358 | } |
359 | |
60bf98ae |
360 | //======================================================================= |
361 | //function : DrawArc |
362 | //purpose : draws the arc between two attach points |
363 | //======================================================================= |
787ff240 |
364 | void PrsDim_AngleDimension::DrawArc (const Handle(Prs3d_Presentation)& thePresentation, |
365 | const gp_Pnt& theFirstAttach, |
366 | const gp_Pnt& theSecondAttach, |
367 | const gp_Pnt& theCenter, |
368 | const Standard_Real theRadius, |
369 | const Standard_Integer theMode) |
60bf98ae |
370 | { |
4d147bf2 |
371 | gp_Pln aPlane (myCenterPoint, GetNormalForMinAngle()); |
60bf98ae |
372 | |
ee905e84 |
373 | // to have an exterior angle presentation, a plane for further constructed circle should be reversed |
787ff240 |
374 | if (myType == PrsDim_TypeOfAngle_Exterior) |
ee905e84 |
375 | { |
376 | gp_Ax1 anAxis = aPlane.Axis(); |
377 | gp_Dir aDir = anAxis.Direction(); |
378 | aDir.Reverse(); |
379 | aPlane.SetAxis(gp_Ax1(anAxis.Location(), aDir)); |
380 | } |
381 | |
60bf98ae |
382 | // construct circle forming the arc |
383 | gce_MakeCirc aConstructCircle (theCenter, aPlane, theRadius); |
384 | if (!aConstructCircle.IsDone()) |
a6eb515f |
385 | { |
60bf98ae |
386 | return; |
7fd59977 |
387 | } |
388 | |
60bf98ae |
389 | gp_Circ aCircle = aConstructCircle.Value(); |
390 | |
391 | // construct the arc |
392 | GC_MakeArcOfCircle aConstructArc (aCircle, theFirstAttach, theSecondAttach, Standard_True); |
393 | if (!aConstructArc.IsDone()) |
a6eb515f |
394 | { |
60bf98ae |
395 | return; |
7fd59977 |
396 | } |
397 | |
60bf98ae |
398 | // generate points with specified deflection |
399 | const Handle(Geom_TrimmedCurve)& anArcCurve = aConstructArc.Value(); |
400 | |
401 | GeomAdaptor_Curve anArcAdaptor (anArcCurve, anArcCurve->FirstParameter(), anArcCurve->LastParameter()); |
7fd59977 |
402 | |
60bf98ae |
403 | // compute number of discretization elements in old-fanshioned way |
404 | gp_Vec aCenterToFirstVec (theCenter, theFirstAttach); |
405 | gp_Vec aCenterToSecondVec (theCenter, theSecondAttach); |
ee905e84 |
406 | Standard_Real anAngle = aCenterToFirstVec.Angle (aCenterToSecondVec); |
787ff240 |
407 | if (myType == PrsDim_TypeOfAngle_Exterior) |
ee905e84 |
408 | anAngle = 2.0 * M_PI - anAngle; |
409 | // it sets 50 points on PI, and a part of points if angle is less |
60bf98ae |
410 | const Standard_Integer aNbPoints = Max (4, Standard_Integer (50.0 * anAngle / M_PI)); |
a6eb515f |
411 | |
60bf98ae |
412 | GCPnts_UniformAbscissa aMakePnts (anArcAdaptor, aNbPoints); |
413 | if (!aMakePnts.IsDone()) |
414 | { |
415 | return; |
7fd59977 |
416 | } |
417 | |
60bf98ae |
418 | // init data arrays for graphical and selection primitives |
419 | Handle(Graphic3d_ArrayOfPolylines) aPrimSegments = new Graphic3d_ArrayOfPolylines (aNbPoints); |
7fd59977 |
420 | |
60bf98ae |
421 | SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve(); |
a6eb515f |
422 | |
60bf98ae |
423 | // load data into arrays |
424 | for (Standard_Integer aPntIt = 1; aPntIt <= aMakePnts.NbPoints(); ++aPntIt) |
a6eb515f |
425 | { |
60bf98ae |
426 | gp_Pnt aPnt = anArcAdaptor.Value (aMakePnts.Parameter (aPntIt)); |
7fd59977 |
427 | |
60bf98ae |
428 | aPrimSegments->AddVertex (aPnt); |
7fd59977 |
429 | |
60bf98ae |
430 | aSensitiveCurve.Append (aPnt); |
a6eb515f |
431 | } |
7fd59977 |
432 | |
60bf98ae |
433 | // add display presentation |
434 | if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All) |
435 | { |
436 | Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True); |
437 | } |
438 | Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect(); |
439 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle); |
440 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments); |
441 | if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All) |
442 | { |
443 | Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False); |
444 | } |
7fd59977 |
445 | } |
a6eb515f |
446 | |
7fd59977 |
447 | //======================================================================= |
60bf98ae |
448 | //function: DrawArcWithText |
a6eb515f |
449 | //purpose : |
7fd59977 |
450 | //======================================================================= |
787ff240 |
451 | void PrsDim_AngleDimension::DrawArcWithText (const Handle(Prs3d_Presentation)& thePresentation, |
452 | const gp_Pnt& theFirstAttach, |
453 | const gp_Pnt& theSecondAttach, |
454 | const gp_Pnt& theCenter, |
455 | const TCollection_ExtendedString& theText, |
456 | const Standard_Real theTextWidth, |
457 | const Standard_Integer theMode, |
458 | const Standard_Integer theLabelPosition) |
7fd59977 |
459 | { |
4d147bf2 |
460 | gp_Pln aPlane (myCenterPoint, GetNormalForMinAngle()); |
461 | |
60bf98ae |
462 | Standard_Real aRadius = theFirstAttach.Distance (myCenterPoint); |
a6eb515f |
463 | |
fe83e1ea |
464 | // construct circle forming the arc |
60bf98ae |
465 | gce_MakeCirc aConstructCircle (theCenter, aPlane, aRadius); |
fe83e1ea |
466 | if (!aConstructCircle.IsDone()) |
467 | { |
468 | return; |
469 | } |
a6eb515f |
470 | |
fe83e1ea |
471 | gp_Circ aCircle = aConstructCircle.Value(); |
a6eb515f |
472 | |
fe83e1ea |
473 | // compute angle parameters of arc end-points on circle |
474 | Standard_Real aParamBeg = ElCLib::Parameter (aCircle, theFirstAttach); |
475 | Standard_Real aParamEnd = ElCLib::Parameter (aCircle, theSecondAttach); |
60bf98ae |
476 | ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); |
a6eb515f |
477 | |
fe83e1ea |
478 | // middle point of arc parameter on circle |
479 | Standard_Real aParamMid = (aParamBeg + aParamEnd) * 0.5; |
a6eb515f |
480 | |
fe83e1ea |
481 | // add text graphical primitives |
482 | if (theMode == ComputeMode_All || theMode == ComputeMode_Text) |
483 | { |
484 | gp_Pnt aTextPos = ElCLib::Value (aParamMid, aCircle); |
60bf98ae |
485 | gp_Dir aTextDir = gce_MakeDir (theFirstAttach, theSecondAttach); |
fe83e1ea |
486 | |
487 | // Drawing text |
7c65581d |
488 | drawText (thePresentation, |
fe83e1ea |
489 | aTextPos, |
490 | aTextDir, |
491 | theText, |
492 | theLabelPosition); |
493 | } |
a6eb515f |
494 | |
fe83e1ea |
495 | if (theMode != ComputeMode_All && theMode != ComputeMode_Line) |
496 | { |
497 | return; |
498 | } |
a6eb515f |
499 | |
fe83e1ea |
500 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
a6eb515f |
501 | |
fe83e1ea |
502 | Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center |
503 | && aDimensionAspect->IsText3d(); |
a6eb515f |
504 | |
fe83e1ea |
505 | if (isLineBreak) |
a6eb515f |
506 | { |
fe83e1ea |
507 | // compute gap for label as parameteric size of sector on circle segment |
4d147bf2 |
508 | Standard_Real aSectorOfText = theTextWidth / aRadius; |
509 | Standard_Real aTextBegin = aParamMid - aSectorOfText * 0.5; |
510 | Standard_Real aTextEnd = aParamMid + aSectorOfText * 0.5; |
511 | gp_Pnt aTextPntBeg = ElCLib::Value (aTextBegin, aCircle); |
512 | gp_Pnt aTextPntEnd = ElCLib::Value (aTextEnd, aCircle); |
fe83e1ea |
513 | |
514 | // Drawing arcs |
4d147bf2 |
515 | if (aTextBegin > aParamBeg) |
516 | { |
517 | DrawArc (thePresentation, theFirstAttach, aTextPntBeg, theCenter, aRadius, theMode); |
518 | } |
519 | if (aTextEnd < aParamEnd) |
520 | { |
521 | DrawArc (thePresentation, aTextPntEnd, theSecondAttach, theCenter, aRadius, theMode); |
522 | } |
fe83e1ea |
523 | } |
524 | else |
525 | { |
60bf98ae |
526 | DrawArc (thePresentation, theFirstAttach, theSecondAttach, theCenter, aRadius, theMode); |
7fd59977 |
527 | } |
a6eb515f |
528 | } |
7fd59977 |
529 | |
a6eb515f |
530 | //======================================================================= |
60bf98ae |
531 | //function : CheckPlane |
532 | //purpose : |
a6eb515f |
533 | //======================================================================= |
787ff240 |
534 | Standard_Boolean PrsDim_AngleDimension::CheckPlane (const gp_Pln& thePlane)const |
a6eb515f |
535 | { |
60bf98ae |
536 | if (!thePlane.Contains (myFirstPoint, Precision::Confusion()) && |
537 | !thePlane.Contains (mySecondPoint, Precision::Confusion()) && |
538 | !thePlane.Contains (myCenterPoint, Precision::Confusion())) |
fe83e1ea |
539 | { |
60bf98ae |
540 | return Standard_False; |
fe83e1ea |
541 | } |
542 | |
60bf98ae |
543 | return Standard_True; |
544 | } |
a6eb515f |
545 | |
60bf98ae |
546 | //======================================================================= |
547 | //function : ComputePlane |
548 | //purpose : |
549 | //======================================================================= |
787ff240 |
550 | void PrsDim_AngleDimension::ComputePlane() |
60bf98ae |
551 | { |
91b16a64 |
552 | if (!myIsGeometryValid) |
a6eb515f |
553 | { |
fe83e1ea |
554 | return; |
7fd59977 |
555 | } |
7fd59977 |
556 | |
4d147bf2 |
557 | // Compute working plane so that Y axis is codirectional |
558 | // with Y axis of text coordinate system (necessary for text alignment) |
559 | gp_Vec aFirstVec = gp_Vec (myCenterPoint, myFirstPoint); |
560 | gp_Vec aSecondVec = gp_Vec (myCenterPoint, mySecondPoint); |
561 | gp_Vec aDirectionN = aSecondVec ^ aFirstVec; |
562 | gp_Vec aDirectionY = aFirstVec + aSecondVec; |
563 | gp_Vec aDirectionX = aDirectionY ^ aDirectionN; |
fe83e1ea |
564 | |
60bf98ae |
565 | myPlane = gp_Pln (gp_Ax3 (myCenterPoint, gp_Dir (aDirectionN), gp_Dir (aDirectionX))); |
566 | } |
7fd59977 |
567 | |
60bf98ae |
568 | //======================================================================= |
569 | //function : GetModelUnits |
570 | //purpose : |
571 | //======================================================================= |
787ff240 |
572 | const TCollection_AsciiString& PrsDim_AngleDimension::GetModelUnits() const |
60bf98ae |
573 | { |
574 | return myDrawer->DimAngleModelUnits(); |
575 | } |
fe83e1ea |
576 | |
60bf98ae |
577 | //======================================================================= |
578 | //function : GetDisplayUnits |
579 | //purpose : |
580 | //======================================================================= |
787ff240 |
581 | const TCollection_AsciiString& PrsDim_AngleDimension::GetDisplayUnits() const |
60bf98ae |
582 | { |
583 | return myDrawer->DimAngleDisplayUnits(); |
584 | } |
fe83e1ea |
585 | |
60bf98ae |
586 | //======================================================================= |
587 | //function : SetModelUnits |
588 | //purpose : |
589 | //======================================================================= |
787ff240 |
590 | void PrsDim_AngleDimension::SetModelUnits (const TCollection_AsciiString& theUnits) |
60bf98ae |
591 | { |
592 | myDrawer->SetDimAngleModelUnits (theUnits); |
593 | } |
fe83e1ea |
594 | |
60bf98ae |
595 | //======================================================================= |
596 | //function : SetDisplayUnits |
597 | //purpose : |
598 | //======================================================================= |
787ff240 |
599 | void PrsDim_AngleDimension::SetDisplayUnits (const TCollection_AsciiString& theUnits) |
60bf98ae |
600 | { |
601 | myDrawer->SetDimAngleDisplayUnits (theUnits); |
602 | } |
603 | |
604 | //======================================================================= |
605 | //function : ComputeValue |
606 | //purpose : |
607 | //======================================================================= |
787ff240 |
608 | Standard_Real PrsDim_AngleDimension::ComputeValue() const |
60bf98ae |
609 | { |
610 | if (!IsValid()) |
a6eb515f |
611 | { |
60bf98ae |
612 | return 0.0; |
7fd59977 |
613 | } |
60bf98ae |
614 | |
615 | gp_Vec aVec1 (myCenterPoint, myFirstPoint); |
616 | gp_Vec aVec2 (myCenterPoint, mySecondPoint); |
617 | |
4d147bf2 |
618 | Standard_Real anAngle = aVec1.AngleWithRef (aVec2, GetNormalForMinAngle()); |
60bf98ae |
619 | |
af203d54 |
620 | return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle); |
7fd59977 |
621 | } |
622 | |
7fd59977 |
623 | //======================================================================= |
a6eb515f |
624 | //function : Compute |
625 | //purpose : Having three gp_Pnt points compute presentation |
7fd59977 |
626 | //======================================================================= |
787ff240 |
627 | void PrsDim_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePM*/, |
628 | const Handle(Prs3d_Presentation)& thePresentation, |
629 | const Standard_Integer theMode) |
a6eb515f |
630 | { |
fe83e1ea |
631 | mySelectionGeom.Clear (theMode); |
7fd59977 |
632 | |
60bf98ae |
633 | if (!IsValid()) |
a6eb515f |
634 | { |
a6eb515f |
635 | return; |
60bf98ae |
636 | } |
7fd59977 |
637 | |
a6eb515f |
638 | // Parameters for presentation |
639 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
d7bffd44 |
640 | |
60bf98ae |
641 | Prs3d_Root::CurrentGroup(thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
d7bffd44 |
642 | |
ee2be2a8 |
643 | Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
d7bffd44 |
644 | |
60bf98ae |
645 | // prepare label string and compute its geometrical width |
646 | Standard_Real aLabelWidth; |
647 | TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); |
d7bffd44 |
648 | |
fe83e1ea |
649 | // add margins to label width |
650 | if (aDimensionAspect->IsText3d()) |
651 | { |
60bf98ae |
652 | aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; |
d7bffd44 |
653 | } |
654 | |
af203d54 |
655 | // Get parameters from aspect or adjust it according with custom text position |
656 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
657 | Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition(); |
7fd59977 |
658 | |
af203d54 |
659 | if (IsTextPositionCustom()) |
d7bffd44 |
660 | { |
91b16a64 |
661 | AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos, myFlyout); |
af203d54 |
662 | } |
fe83e1ea |
663 | |
af203d54 |
664 | // Handle user-defined and automatic arrow placement |
665 | Standard_Boolean isArrowsExternal = Standard_False; |
666 | Standard_Integer aLabelPosition = LabelPosition_None; |
fe83e1ea |
667 | |
af203d54 |
668 | FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal); |
d7bffd44 |
669 | |
af203d54 |
670 | gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); |
671 | gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); |
7fd59977 |
672 | |
a6eb515f |
673 | //Arrows positions and directions |
4d147bf2 |
674 | gp_Vec aWorkingPlaneDir (GetNormalForMinAngle()); |
d7bffd44 |
675 | |
4d147bf2 |
676 | gp_Dir aFirstExtensionDir = aWorkingPlaneDir.Reversed() ^ gp_Vec (myCenterPoint, aFirstAttach); |
677 | gp_Dir aSecondExtensionDir = aWorkingPlaneDir ^ gp_Vec (myCenterPoint, aSecondAttach); |
7fd59977 |
678 | |
d7bffd44 |
679 | gp_Vec aFirstArrowVec = gp_Vec (aFirstExtensionDir) * anArrowLength; |
680 | gp_Vec aSecondArrowVec = gp_Vec (aSecondExtensionDir) * anArrowLength; |
7fd59977 |
681 | |
d7bffd44 |
682 | if (isArrowsExternal) |
a6eb515f |
683 | { |
684 | aFirstArrowVec.Reverse(); |
685 | aSecondArrowVec.Reverse(); |
d7bffd44 |
686 | } |
687 | |
4d147bf2 |
688 | gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0); |
689 | gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0); |
690 | gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0); |
691 | gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0); |
692 | |
d7bffd44 |
693 | aFirstArrowBegin = aFirstAttach; |
694 | aSecondArrowBegin = aSecondAttach; |
695 | aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec); |
696 | aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec); |
697 | |
d7bffd44 |
698 | // Group1: stenciling text and the angle dimension arc |
699 | Prs3d_Root::NewGroup (thePresentation); |
700 | |
d7bffd44 |
701 | Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask; |
702 | |
703 | // draw text label |
704 | switch (aHPosition) |
b8ddfc2f |
705 | { |
d7bffd44 |
706 | case LabelPosition_HCenter : |
a6eb515f |
707 | { |
d7bffd44 |
708 | Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center |
709 | && aDimensionAspect->IsText3d(); |
710 | |
711 | if (isLineBreak) |
712 | { |
60bf98ae |
713 | DrawArcWithText (thePresentation, |
d7bffd44 |
714 | aFirstAttach, |
715 | aSecondAttach, |
60bf98ae |
716 | myCenterPoint, |
717 | aLabelString, |
718 | aLabelWidth, |
fe83e1ea |
719 | theMode, |
d7bffd44 |
720 | aLabelPosition); |
721 | break; |
722 | } |
723 | |
fe83e1ea |
724 | // compute text primitives |
725 | if (theMode == ComputeMode_All || theMode == ComputeMode_Text) |
d7bffd44 |
726 | { |
60bf98ae |
727 | gp_Vec aDimensionDir (aFirstAttach, aSecondAttach); |
af203d54 |
728 | gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition |
729 | : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint); |
60bf98ae |
730 | gp_Dir aTextDir = aDimensionDir; |
fe83e1ea |
731 | |
7c65581d |
732 | drawText (thePresentation, |
fe83e1ea |
733 | aTextPos, |
734 | aTextDir, |
60bf98ae |
735 | aLabelString, |
fe83e1ea |
736 | aLabelPosition); |
d7bffd44 |
737 | } |
738 | |
fe83e1ea |
739 | if (theMode == ComputeMode_All || theMode == ComputeMode_Line) |
740 | { |
60bf98ae |
741 | DrawArc (thePresentation, |
787ff240 |
742 | (isArrowsExternal || !isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_First)) ? aFirstAttach : aFirstArrowEnd, |
743 | (isArrowsExternal || !isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_Second)) ? aSecondAttach : aSecondArrowEnd, |
60bf98ae |
744 | myCenterPoint, |
fe83e1ea |
745 | Abs (GetFlyout()), |
746 | theMode); |
747 | } |
a6eb515f |
748 | } |
d7bffd44 |
749 | break; |
750 | |
751 | case LabelPosition_Left : |
a6eb515f |
752 | { |
60bf98ae |
753 | DrawExtension (thePresentation, |
d7bffd44 |
754 | anExtensionSize, |
787ff240 |
755 | (isArrowsExternal && isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_First)) ? aFirstArrowEnd : aFirstAttach, |
d7bffd44 |
756 | aFirstExtensionDir, |
60bf98ae |
757 | aLabelString, |
758 | aLabelWidth, |
fe83e1ea |
759 | theMode, |
d7bffd44 |
760 | aLabelPosition); |
a6eb515f |
761 | } |
d7bffd44 |
762 | break; |
763 | |
764 | case LabelPosition_Right : |
a6eb515f |
765 | { |
60bf98ae |
766 | DrawExtension (thePresentation, |
d7bffd44 |
767 | anExtensionSize, |
787ff240 |
768 | (isArrowsExternal && isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_Second)) ? aSecondArrowEnd : aSecondAttach, |
d7bffd44 |
769 | aSecondExtensionDir, |
60bf98ae |
770 | aLabelString, |
771 | aLabelWidth, |
fe83e1ea |
772 | theMode, |
d7bffd44 |
773 | aLabelPosition); |
a6eb515f |
774 | } |
d7bffd44 |
775 | break; |
776 | } |
777 | |
778 | // dimension arc without text |
fe83e1ea |
779 | if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && aHPosition != LabelPosition_HCenter) |
d7bffd44 |
780 | { |
781 | Prs3d_Root::NewGroup (thePresentation); |
782 | |
60bf98ae |
783 | DrawArc (thePresentation, |
787ff240 |
784 | (isArrowsExternal || !isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_First)) ? aFirstAttach : aFirstArrowEnd, |
785 | (isArrowsExternal || !isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_Second)) ? aSecondAttach : aSecondArrowEnd, |
60bf98ae |
786 | myCenterPoint, |
d7bffd44 |
787 | Abs(GetFlyout ()), |
fe83e1ea |
788 | theMode); |
d7bffd44 |
789 | } |
7fd59977 |
790 | |
d7bffd44 |
791 | // arrows and arrow extensions |
fe83e1ea |
792 | if (theMode == ComputeMode_All || theMode == ComputeMode_Line) |
d7bffd44 |
793 | { |
794 | Prs3d_Root::NewGroup (thePresentation); |
795 | |
787ff240 |
796 | if (isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_First)) |
ee905e84 |
797 | DrawArrow (thePresentation, aFirstArrowBegin, gp_Dir (aFirstArrowVec)); |
787ff240 |
798 | if (isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_Second)) |
ee905e84 |
799 | DrawArrow (thePresentation, aSecondArrowBegin, gp_Dir (aSecondArrowVec)); |
d7bffd44 |
800 | } |
801 | |
fe83e1ea |
802 | if ((theMode == ComputeMode_All || theMode == ComputeMode_Line) && isArrowsExternal) |
d7bffd44 |
803 | { |
804 | Prs3d_Root::NewGroup (thePresentation); |
805 | |
787ff240 |
806 | if (aHPosition != LabelPosition_Left && isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_First)) |
d7bffd44 |
807 | { |
60bf98ae |
808 | DrawExtension (thePresentation, |
af203d54 |
809 | aDimensionAspect->ArrowTailSize(), |
d7bffd44 |
810 | aFirstArrowEnd, |
811 | aFirstExtensionDir, |
fe83e1ea |
812 | THE_EMPTY_LABEL_STRING, |
813 | THE_EMPTY_LABEL_WIDTH, |
814 | theMode, |
d7bffd44 |
815 | LabelPosition_None); |
816 | } |
817 | |
787ff240 |
818 | if (aHPosition != LabelPosition_Right && isArrowVisible(PrsDim_TypeOfAngleArrowVisibility_Second)) |
a6eb515f |
819 | { |
60bf98ae |
820 | DrawExtension (thePresentation, |
af203d54 |
821 | aDimensionAspect->ArrowTailSize(), |
d7bffd44 |
822 | aSecondArrowEnd, |
823 | aSecondExtensionDir, |
fe83e1ea |
824 | THE_EMPTY_LABEL_STRING, |
825 | THE_EMPTY_LABEL_WIDTH, |
826 | theMode, |
d7bffd44 |
827 | LabelPosition_None); |
a6eb515f |
828 | } |
829 | } |
7fd59977 |
830 | |
d7bffd44 |
831 | // flyouts |
60bf98ae |
832 | if (theMode == ComputeMode_All) |
a6eb515f |
833 | { |
d7bffd44 |
834 | Prs3d_Root::NewGroup (thePresentation); |
835 | |
836 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (4); |
60bf98ae |
837 | aPrimSegments->AddVertex (myCenterPoint); |
a6eb515f |
838 | aPrimSegments->AddVertex (aFirstAttach); |
60bf98ae |
839 | aPrimSegments->AddVertex (myCenterPoint); |
a6eb515f |
840 | aPrimSegments->AddVertex (aSecondAttach); |
d7bffd44 |
841 | |
842 | Handle(Graphic3d_AspectLine3d) aFlyoutStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect(); |
843 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aFlyoutStyle); |
a6eb515f |
844 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments); |
7fd59977 |
845 | } |
846 | |
91b16a64 |
847 | mySelectionGeom.IsComputed = Standard_True; |
7fd59977 |
848 | } |
62b6361a |
849 | |
850 | //======================================================================= |
60bf98ae |
851 | //function : ComputeFlyoutSelection |
62b6361a |
852 | //purpose : computes selection for flyouts |
853 | //======================================================================= |
787ff240 |
854 | void PrsDim_AngleDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection, |
855 | const Handle(SelectMgr_EntityOwner)& theOwner) |
62b6361a |
856 | { |
60bf98ae |
857 | gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); |
858 | gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); |
859 | |
860 | Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner); |
861 | aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aFirstAttach)); |
862 | aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myCenterPoint, aSecondAttach)); |
863 | |
864 | theSelection->Add (aSensitiveEntity); |
865 | } |
866 | |
867 | //======================================================================= |
868 | //function : InitTwoEdgesAngle |
869 | //purpose : |
870 | //======================================================================= |
787ff240 |
871 | Standard_Boolean PrsDim_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane) |
60bf98ae |
872 | { |
873 | TopoDS_Edge aFirstEdge = TopoDS::Edge (myFirstShape); |
874 | TopoDS_Edge aSecondEdge = TopoDS::Edge (mySecondShape); |
875 | |
876 | BRepAdaptor_Curve aMakeFirstLine (aFirstEdge); |
877 | BRepAdaptor_Curve aMakeSecondLine (aSecondEdge); |
878 | |
879 | if (aMakeFirstLine.GetType() != GeomAbs_Line || aMakeSecondLine.GetType() != GeomAbs_Line) |
fe83e1ea |
880 | { |
60bf98ae |
881 | return Standard_False; |
fe83e1ea |
882 | } |
883 | |
60bf98ae |
884 | Handle(Geom_Line) aFirstLine = new Geom_Line (aMakeFirstLine.Line()); |
885 | Handle(Geom_Line) aSecondLine = new Geom_Line (aMakeSecondLine.Line()); |
fe83e1ea |
886 | |
60bf98ae |
887 | gp_Lin aFirstLin = aFirstLine->Lin(); |
888 | gp_Lin aSecondLin = aSecondLine->Lin(); |
fe83e1ea |
889 | |
4d147bf2 |
890 | Standard_Boolean isParallelLines = aFirstLin.Direction().IsParallel (aSecondLin.Direction(), Precision::Angular()); |
60bf98ae |
891 | |
4d147bf2 |
892 | theComputedPlane = isParallelLines ? gp_Pln(gp::XOY()) |
893 | : gp_Pln (aSecondLin.Location(), gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction())); |
60bf98ae |
894 | |
4d147bf2 |
895 | // Compute geometry for this plane and edges |
60bf98ae |
896 | Standard_Boolean isInfinite1,isInfinite2; |
897 | gp_Pnt aFirstPoint1, aLastPoint1, aFirstPoint2, aLastPoint2; |
aa00364d |
898 | Handle(Geom_Curve) aFirstCurve = aFirstLine, aSecondCurve = aSecondLine; |
787ff240 |
899 | if (!PrsDim::ComputeGeometry (aFirstEdge, aSecondEdge, |
900 | aFirstCurve, aSecondCurve, |
901 | aFirstPoint1, aLastPoint1, |
902 | aFirstPoint2, aLastPoint2, |
903 | isInfinite1, isInfinite2)) |
60bf98ae |
904 | { |
905 | return Standard_False; |
906 | } |
907 | |
4d147bf2 |
908 | Standard_Boolean isSameLines = aFirstLin.Direction().IsEqual (aSecondLin.Direction(), Precision::Angular()) |
909 | && aFirstLin.Location().IsEqual (aSecondLin.Location(),Precision::Confusion()); |
910 | |
911 | // It can be the same gp_Lin geometry but the different begin and end parameters |
912 | Standard_Boolean isSameEdges = |
913 | (aFirstPoint1.IsEqual (aFirstPoint2, Precision::Confusion()) && aLastPoint1.IsEqual (aLastPoint2, Precision::Confusion())) |
914 | || (aFirstPoint1.IsEqual (aLastPoint2, Precision::Confusion()) && aLastPoint1.IsEqual (aFirstPoint2, Precision::Confusion())); |
60bf98ae |
915 | |
4d147bf2 |
916 | if (isParallelLines) |
917 | { |
918 | // Zero angle, it could not handle this geometry |
919 | if (isSameLines && isSameEdges) |
60bf98ae |
920 | { |
4d147bf2 |
921 | return Standard_False; |
60bf98ae |
922 | } |
923 | |
4d147bf2 |
924 | // Handle the case of Pi angle |
925 | const Standard_Real aParam11 = ElCLib::Parameter (aFirstLin, aFirstPoint1); |
926 | const Standard_Real aParam12 = ElCLib::Parameter (aFirstLin, aLastPoint1); |
927 | const Standard_Real aParam21 = ElCLib::Parameter (aFirstLin, aFirstPoint2); |
928 | const Standard_Real aParam22 = ElCLib::Parameter (aFirstLin, aLastPoint2); |
929 | myCenterPoint = ElCLib::Value ( (Min (aParam11, aParam12) + Max (aParam21, aParam22)) * 0.5, aFirstLin); |
930 | myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout())); |
931 | mySecondPoint = myCenterPoint.XYZ() + (aFirstLin.Direction().IsEqual (aSecondLin.Direction(), Precision::Angular()) |
932 | ? aFirstLin.Direction().Reversed().XYZ() * Abs (GetFlyout()) |
933 | : aSecondLin.Direction().XYZ() * Abs (GetFlyout())); |
60bf98ae |
934 | } |
935 | else |
936 | { |
937 | // Find intersection |
938 | gp_Lin2d aFirstLin2d = ProjLib::Project (theComputedPlane, aFirstLin); |
939 | gp_Lin2d aSecondLin2d = ProjLib::Project (theComputedPlane, aSecondLin); |
940 | |
941 | IntAna2d_AnaIntersection anInt2d (aFirstLin2d, aSecondLin2d); |
942 | gp_Pnt2d anIntersectPoint; |
943 | if (!anInt2d.IsDone() || anInt2d.IsEmpty()) |
944 | { |
945 | return Standard_False; |
946 | } |
947 | |
948 | anIntersectPoint = gp_Pnt2d (anInt2d.Point(1).Value()); |
949 | myCenterPoint = ElCLib::To3d (theComputedPlane.Position().Ax2(), anIntersectPoint); |
950 | |
951 | if (isInfinite1 || isInfinite2) |
952 | { |
953 | myFirstPoint = myCenterPoint.Translated (gp_Vec (aFirstLin.Direction()) * Abs (GetFlyout())); |
954 | mySecondPoint = myCenterPoint.Translated (gp_Vec (aSecondLin.Direction()) * Abs (GetFlyout())); |
955 | |
956 | return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
957 | } |
958 | |
959 | // | |
960 | // | <- dimension should be here |
961 | // *---- |
962 | myFirstPoint = myCenterPoint.Distance (aFirstPoint1) > myCenterPoint.Distance (aLastPoint1) |
963 | ? aFirstPoint1 |
964 | : aLastPoint1; |
965 | |
966 | mySecondPoint = myCenterPoint.Distance (aFirstPoint2) > myCenterPoint.Distance (aLastPoint2) |
967 | ? aFirstPoint2 |
968 | : aLastPoint2; |
969 | } |
970 | |
971 | return IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
972 | } |
973 | |
974 | //======================================================================= |
975 | //function : InitTwoFacesAngle |
976 | //purpose : initialization of angle dimension between two faces |
977 | //======================================================================= |
787ff240 |
978 | Standard_Boolean PrsDim_AngleDimension::InitTwoFacesAngle() |
60bf98ae |
979 | { |
980 | TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape); |
981 | TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape); |
982 | |
983 | gp_Dir aFirstDir, aSecondDir; |
51740958 |
984 | gp_Pln aFirstPln, aSecondPln; |
60bf98ae |
985 | Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf; |
787ff240 |
986 | PrsDim_KindOfSurface aFirstSurfType, aSecondSurfType; |
60bf98ae |
987 | Standard_Real aFirstOffset, aSecondOffset; |
988 | |
787ff240 |
989 | PrsDim::GetPlaneFromFace (aFirstFace, aFirstPln, |
990 | aFirstBasisSurf,aFirstSurfType,aFirstOffset); |
60bf98ae |
991 | |
787ff240 |
992 | PrsDim::GetPlaneFromFace (aSecondFace, aSecondPln, |
993 | aSecondBasisSurf, aSecondSurfType, aSecondOffset); |
60bf98ae |
994 | |
787ff240 |
995 | if (aFirstSurfType == PrsDim_KOS_Plane && aSecondSurfType == PrsDim_KOS_Plane) |
60bf98ae |
996 | { |
997 | //Planar faces angle |
998 | Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf); |
999 | Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf); |
787ff240 |
1000 | return PrsDim::InitAngleBetweenPlanarFaces (aFirstFace, aSecondFace, |
1001 | myCenterPoint, myFirstPoint, mySecondPoint) |
1002 | && IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
60bf98ae |
1003 | } |
1004 | else |
1005 | { |
1006 | // Curvilinear faces angle |
787ff240 |
1007 | return PrsDim::InitAngleBetweenCurvilinearFaces (aFirstFace, aSecondFace, |
1008 | aFirstSurfType, aSecondSurfType, |
1009 | myCenterPoint, myFirstPoint, mySecondPoint) |
1010 | && IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
60bf98ae |
1011 | } |
1012 | } |
1013 | |
1014 | //======================================================================= |
1015 | //function : InitTwoFacesAngle |
1016 | //purpose : initialization of angle dimension between two faces |
1017 | //======================================================================= |
787ff240 |
1018 | Standard_Boolean PrsDim_AngleDimension::InitTwoFacesAngle (const gp_Pnt& thePointOnFirstFace) |
60bf98ae |
1019 | { |
1020 | TopoDS_Face aFirstFace = TopoDS::Face (myFirstShape); |
1021 | TopoDS_Face aSecondFace = TopoDS::Face (mySecondShape); |
1022 | |
1023 | gp_Dir aFirstDir, aSecondDir; |
51740958 |
1024 | gp_Pln aFirstPln, aSecondPln; |
60bf98ae |
1025 | Handle(Geom_Surface) aFirstBasisSurf, aSecondBasisSurf; |
787ff240 |
1026 | PrsDim_KindOfSurface aFirstSurfType, aSecondSurfType; |
60bf98ae |
1027 | Standard_Real aFirstOffset, aSecondOffset; |
1028 | |
787ff240 |
1029 | PrsDim::GetPlaneFromFace (aFirstFace, aFirstPln, |
1030 | aFirstBasisSurf,aFirstSurfType,aFirstOffset); |
60bf98ae |
1031 | |
787ff240 |
1032 | PrsDim::GetPlaneFromFace (aSecondFace, aSecondPln, |
1033 | aSecondBasisSurf, aSecondSurfType, aSecondOffset); |
60bf98ae |
1034 | |
1035 | myFirstPoint = thePointOnFirstFace; |
787ff240 |
1036 | if (aFirstSurfType == PrsDim_KOS_Plane && aSecondSurfType == PrsDim_KOS_Plane) |
60bf98ae |
1037 | { |
1038 | //Planar faces angle |
1039 | Handle(Geom_Plane) aFirstPlane = Handle(Geom_Plane)::DownCast (aFirstBasisSurf); |
1040 | Handle(Geom_Plane) aSecondPlane = Handle(Geom_Plane)::DownCast (aSecondBasisSurf); |
787ff240 |
1041 | return PrsDim::InitAngleBetweenPlanarFaces (aFirstFace, aSecondFace, |
1042 | myCenterPoint, myFirstPoint, mySecondPoint, |
1043 | Standard_True) |
1044 | && IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
60bf98ae |
1045 | } |
1046 | else |
1047 | { |
1048 | // Curvilinear faces angle |
787ff240 |
1049 | return PrsDim::InitAngleBetweenCurvilinearFaces (aFirstFace, aSecondFace, |
1050 | aFirstSurfType, aSecondSurfType, |
1051 | myCenterPoint, myFirstPoint, mySecondPoint, |
1052 | Standard_True) |
1053 | && IsValidPoints (myFirstPoint, myCenterPoint, mySecondPoint); |
60bf98ae |
1054 | } |
1055 | } |
1056 | |
1057 | //======================================================================= |
1058 | //function : InitConeAngle |
1059 | //purpose : initialization of the cone angle |
1060 | //======================================================================= |
787ff240 |
1061 | Standard_Boolean PrsDim_AngleDimension::InitConeAngle() |
60bf98ae |
1062 | { |
1063 | if (myFirstShape.IsNull()) |
1064 | { |
1065 | return Standard_False; |
1066 | } |
1067 | |
1068 | TopoDS_Face aConeShape = TopoDS::Face (myFirstShape); |
1069 | gp_Pln aPln; |
1070 | gp_Cone aCone; |
1071 | gp_Circ aCircle; |
1072 | // A surface from the Face |
1073 | Handle(Geom_Surface) aSurf; |
1074 | Handle(Geom_OffsetSurface) aOffsetSurf; |
1075 | Handle(Geom_ConicalSurface) aConicalSurf; |
1076 | Handle(Geom_SurfaceOfRevolution) aRevSurf; |
1077 | Handle(Geom_Line) aLine; |
1078 | BRepAdaptor_Surface aConeAdaptor (aConeShape); |
1079 | TopoDS_Face aFace; |
787ff240 |
1080 | PrsDim_KindOfSurface aSurfType; |
60bf98ae |
1081 | Standard_Real anOffset = 0.; |
1082 | Handle(Standard_Type) aType; |
1083 | |
787ff240 |
1084 | const Standard_Real aMaxV = aConeAdaptor.FirstVParameter(); |
1085 | const Standard_Real aMinV = aConeAdaptor.LastVParameter(); |
1086 | PrsDim::GetPlaneFromFace (aConeShape, aPln, aSurf, aSurfType, anOffset); |
1087 | if (aSurfType == PrsDim_KOS_Revolution) |
60bf98ae |
1088 | { |
1089 | // Surface of revolution |
1090 | aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aSurf); |
1091 | gp_Lin aLin (aRevSurf->Axis()); |
1092 | Handle(Geom_Curve) aBasisCurve = aRevSurf->BasisCurve(); |
1093 | //Must be a part of line (basis curve should be linear) |
1094 | if (aBasisCurve ->DynamicType() != STANDARD_TYPE(Geom_Line)) |
1095 | return Standard_False; |
1096 | |
1097 | gp_Pnt aFirst1 = aConeAdaptor.Value (0., aMinV); |
1098 | gp_Pnt aLast1 = aConeAdaptor.Value (0., aMaxV); |
1099 | gp_Vec aVec1 (aFirst1, aLast1); |
1100 | |
1101 | //Projection <aFirst> on <aLin> |
1102 | gp_Pnt aFirst2 = ElCLib::Value (ElCLib::Parameter (aLin, aFirst1), aLin); |
1103 | // Projection <aLast> on <aLin> |
1104 | gp_Pnt aLast2 = ElCLib::Value (ElCLib::Parameter (aLin, aLast1), aLin); |
1105 | |
1106 | gp_Vec aVec2 (aFirst2, aLast2); |
1107 | |
1108 | // Check if two parts of revolution are parallel (it's a cylinder) or normal (it's a circle). |
1109 | if (aVec1.IsParallel (aVec2, Precision::Angular()) |
1110 | || aVec1.IsNormal (aVec2,Precision::Angular())) |
1111 | return Standard_False; |
1112 | |
1113 | gce_MakeCone aMkCone (aRevSurf->Axis(), aFirst1, aLast1); |
1114 | aCone = aMkCone.Value(); |
1115 | myCenterPoint = aCone.Apex(); |
1116 | } |
1117 | else |
1118 | { |
1119 | aType = aSurf->DynamicType(); |
1120 | if (aType == STANDARD_TYPE(Geom_OffsetSurface) || anOffset > 0.01) |
1121 | { |
1122 | // Offset surface |
1123 | aOffsetSurf = new Geom_OffsetSurface (aSurf, anOffset); |
1124 | aSurf = aOffsetSurf->Surface(); |
1125 | BRepBuilderAPI_MakeFace aMkFace(aSurf, Precision::Confusion()); |
1126 | aMkFace.Build(); |
1127 | if (!aMkFace.IsDone()) |
1128 | return Standard_False; |
1129 | aConeAdaptor.Initialize (aMkFace.Face()); |
1130 | } |
1131 | aCone = aConeAdaptor.Cone(); |
1132 | aConicalSurf = Handle(Geom_ConicalSurface)::DownCast (aSurf); |
1133 | myCenterPoint = aConicalSurf->Apex(); |
1134 | } |
1135 | |
1136 | // A circle where the angle is drawn |
1137 | Handle(Geom_Curve) aCurve; |
1138 | Standard_Real aMidV = ( aMinV + aMaxV ) / 2.5; |
1139 | aCurve = aSurf->VIso (aMidV); |
1140 | aCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); |
1141 | |
1142 | aCurve = aSurf->VIso(aMaxV); |
1143 | gp_Circ aCircVmax = Handle(Geom_Circle)::DownCast(aCurve)->Circ(); |
1144 | aCurve = aSurf->VIso(aMinV); |
1145 | gp_Circ aCircVmin = Handle(Geom_Circle)::DownCast(aCurve)->Circ(); |
1146 | |
1147 | if (aCircVmax.Radius() < aCircVmin.Radius()) |
1148 | { |
1149 | gp_Circ aTmpCirc = aCircVmax; |
1150 | aCircVmax = aCircVmin; |
1151 | aCircVmin = aTmpCirc; |
1152 | } |
1153 | |
1154 | myFirstPoint = ElCLib::Value (0, aCircle); |
1155 | mySecondPoint = ElCLib::Value (M_PI, aCircle); |
1156 | return Standard_True; |
1157 | } |
1158 | |
1159 | //======================================================================= |
1160 | //function : IsValidPoints |
1161 | //purpose : |
1162 | //======================================================================= |
787ff240 |
1163 | Standard_Boolean PrsDim_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint, |
1164 | const gp_Pnt& theCenterPoint, |
1165 | const gp_Pnt& theSecondPoint) const |
60bf98ae |
1166 | { |
1167 | return theFirstPoint.Distance (theCenterPoint) > Precision::Confusion() |
1168 | && theSecondPoint.Distance (theCenterPoint) > Precision::Confusion() |
1169 | && gp_Vec (theCenterPoint, theFirstPoint).Angle ( |
1170 | gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular(); |
d7bffd44 |
1171 | } |
af203d54 |
1172 | |
ee905e84 |
1173 | //======================================================================= |
1174 | //function : isArrowVisible |
1175 | //purpose : compares given and internal arrows types, returns true if the the type should be shown |
1176 | //======================================================================= |
787ff240 |
1177 | Standard_Boolean PrsDim_AngleDimension::isArrowVisible(const PrsDim_TypeOfAngleArrowVisibility theArrowType) const |
ee905e84 |
1178 | { |
1179 | switch (theArrowType) |
1180 | { |
787ff240 |
1181 | case PrsDim_TypeOfAngleArrowVisibility_Both: |
1182 | return myArrowsVisibility == PrsDim_TypeOfAngleArrowVisibility_Both; |
1183 | case PrsDim_TypeOfAngleArrowVisibility_First: |
1184 | return myArrowsVisibility == PrsDim_TypeOfAngleArrowVisibility_Both || myArrowsVisibility == PrsDim_TypeOfAngleArrowVisibility_First; |
1185 | case PrsDim_TypeOfAngleArrowVisibility_Second: |
1186 | return myArrowsVisibility == PrsDim_TypeOfAngleArrowVisibility_Both || myArrowsVisibility == PrsDim_TypeOfAngleArrowVisibility_Second; |
1187 | case PrsDim_TypeOfAngleArrowVisibility_None: |
ee905e84 |
1188 | return false; |
1189 | } |
1190 | return false; |
1191 | } |
1192 | |
af203d54 |
1193 | //======================================================================= |
1194 | //function : GetTextPosition |
1195 | //purpose : |
1196 | //======================================================================= |
787ff240 |
1197 | gp_Pnt PrsDim_AngleDimension::GetTextPosition() const |
af203d54 |
1198 | { |
1199 | if (!IsValid()) |
1200 | { |
1201 | return gp::Origin(); |
1202 | } |
1203 | |
1204 | if (IsTextPositionCustom()) |
1205 | { |
1206 | return myFixedTextPosition; |
1207 | } |
1208 | |
1209 | // Counts text position according to the dimension parameters |
1210 | gp_Pnt aTextPosition (gp::Origin()); |
1211 | |
1212 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
1213 | |
1214 | // Prepare label string and compute its geometrical width |
1215 | Standard_Real aLabelWidth; |
1216 | TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); |
1217 | |
1218 | gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); |
1219 | gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); |
1220 | |
1221 | // Handle user-defined and automatic arrow placement |
1222 | Standard_Boolean isArrowsExternal = Standard_False; |
1223 | Standard_Integer aLabelPosition = LabelPosition_None; |
1224 | FitTextAlignment (aDimensionAspect->TextHorizontalPosition(), |
1225 | aLabelPosition, isArrowsExternal); |
1226 | |
1227 | // Get text position |
1228 | switch (aLabelPosition & LabelPosition_HMask) |
1229 | { |
1230 | case LabelPosition_HCenter: |
1231 | { |
1232 | aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint); |
1233 | } |
1234 | break; |
1235 | case LabelPosition_Left: |
1236 | { |
1237 | gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach); |
1238 | gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach); |
1239 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
1240 | Standard_Real anOffset = isArrowsExternal |
1241 | ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() |
1242 | : anExtensionSize; |
1243 | gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * -anOffset; |
1244 | aTextPosition = aFirstAttach.Translated (anExtensionVec); |
1245 | } |
1246 | break; |
1247 | case LabelPosition_Right: |
1248 | { |
1249 | gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach); |
1250 | gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach); |
1251 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
1252 | Standard_Real anOffset = isArrowsExternal |
1253 | ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() |
1254 | : anExtensionSize; |
1255 | gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * anOffset; |
1256 | aTextPosition = aSecondAttach.Translated (anExtensionVec); |
1257 | } |
1258 | break; |
1259 | } |
1260 | |
1261 | return aTextPosition; |
1262 | } |
1263 | |
1264 | //======================================================================= |
1265 | //function : SetTextPosition |
1266 | //purpose : |
1267 | //======================================================================= |
787ff240 |
1268 | void PrsDim_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos) |
af203d54 |
1269 | { |
1270 | if (!IsValid()) |
1271 | { |
1272 | return; |
1273 | } |
1274 | |
1275 | // The text position point for angle dimension should belong to the working plane. |
1276 | if (!GetPlane().Contains (theTextPos, Precision::Confusion())) |
1277 | { |
9775fa61 |
1278 | throw Standard_ProgramError("The text position point for angle dimension doesn't belong to the working plane."); |
af203d54 |
1279 | } |
1280 | |
1281 | myIsTextPositionFixed = Standard_True; |
1282 | myFixedTextPosition = theTextPos; |
1283 | } |
1284 | |
1285 | //======================================================================= |
91b16a64 |
1286 | //function : AdjustParameters |
af203d54 |
1287 | //purpose : |
1288 | //======================================================================= |
787ff240 |
1289 | void PrsDim_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos, |
1290 | Standard_Real& theExtensionSize, |
1291 | Prs3d_DimensionTextHorizontalPosition& theAlignment, |
1292 | Standard_Real& theFlyout) const |
af203d54 |
1293 | { |
1294 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
1295 | Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
1296 | |
af203d54 |
1297 | // Build circle with radius that is equal to distance from text position to the center point. |
1298 | Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude(); |
1299 | |
1300 | // Set attach points in positive direction of the flyout. |
1301 | gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius); |
1302 | gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius); |
1303 | |
1304 | gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius); |
1305 | if (!aConstructCircle.IsDone()) |
1306 | { |
1307 | return; |
1308 | } |
1309 | gp_Circ aCircle = aConstructCircle.Value(); |
1310 | |
1311 | // Default values |
1312 | theExtensionSize = aDimensionAspect->ArrowAspect()->Length(); |
1313 | theAlignment = Prs3d_DTHP_Center; |
1314 | |
1315 | Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach); |
1316 | Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach); |
1317 | if (aParamEnd < aParamBeg) |
1318 | { |
1319 | Standard_Real aParam = aParamEnd; |
1320 | aParamEnd = aParamBeg; |
1321 | aParamBeg = aParam; |
1322 | } |
1323 | |
1324 | ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); |
1325 | Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos); |
1326 | |
1327 | // Horizontal center |
1328 | if (aTextPar > aParamBeg && aTextPar < aParamEnd) |
1329 | { |
91b16a64 |
1330 | theFlyout = aRadius; |
af203d54 |
1331 | return; |
1332 | } |
1333 | |
1334 | aParamBeg += M_PI; |
1335 | aParamEnd += M_PI; |
1336 | ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); |
1337 | |
1338 | if (aTextPar > aParamBeg && aTextPar < aParamEnd) |
1339 | { |
91b16a64 |
1340 | theFlyout = -aRadius; |
af203d54 |
1341 | return; |
1342 | } |
1343 | |
1344 | // Text on the extensions |
1345 | gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint); |
1346 | gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint); |
787ff240 |
1347 | gp_Pnt aFirstTextProj = PrsDim::Nearest (aFirstLine, theTextPos); |
1348 | gp_Pnt aSecondTextProj = PrsDim::Nearest (aSecondLine, theTextPos); |
af203d54 |
1349 | Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos); |
1350 | Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos); |
1351 | |
1352 | if (aFirstDist <= aSecondDist) |
1353 | { |
1354 | aRadius = myCenterPoint.Distance (aFirstTextProj); |
1355 | Standard_Real aNewExtensionSize = aFirstDist - anArrowLength; |
1356 | theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize; |
1357 | |
1358 | theAlignment = Prs3d_DTHP_Left; |
1359 | |
1360 | gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius); |
1361 | |
91b16a64 |
1362 | theFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion() |
af203d54 |
1363 | ? -aRadius : aRadius; |
1364 | } |
1365 | else |
1366 | { |
1367 | aRadius = myCenterPoint.Distance (aSecondTextProj); |
1368 | |
1369 | Standard_Real aNewExtensionSize = aSecondDist - anArrowLength; |
1370 | |
1371 | theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize; |
1372 | |
1373 | theAlignment = Prs3d_DTHP_Right; |
1374 | |
1375 | gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius); |
1376 | |
91b16a64 |
1377 | theFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion() |
af203d54 |
1378 | ? -aRadius : aRadius; |
1379 | } |
1380 | } |
1381 | |
1382 | //======================================================================= |
1383 | //function : FitTextAlignment |
1384 | //purpose : |
1385 | //======================================================================= |
787ff240 |
1386 | void PrsDim_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, |
1387 | Standard_Integer& theLabelPosition, |
1388 | Standard_Boolean& theIsArrowsExternal) const |
af203d54 |
1389 | { |
1390 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
1391 | |
ee2be2a8 |
1392 | Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
af203d54 |
1393 | |
1394 | // Prepare label string and compute its geometrical width |
1395 | Standard_Real aLabelWidth; |
1396 | TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); |
1397 | |
1398 | // add margins to label width |
1399 | if (aDimensionAspect->IsText3d()) |
1400 | { |
1401 | aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; |
1402 | } |
1403 | |
1404 | gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); |
1405 | gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); |
1406 | |
1407 | // Handle user-defined and automatic arrow placement |
1408 | switch (aDimensionAspect->ArrowOrientation()) |
1409 | { |
1410 | case Prs3d_DAO_External: theIsArrowsExternal = true; break; |
1411 | case Prs3d_DAO_Internal: theIsArrowsExternal = false; break; |
1412 | case Prs3d_DAO_Fit: |
1413 | { |
1414 | gp_Vec anAttachVector (aFirstAttach, aSecondAttach); |
1415 | Standard_Real aDimensionWidth = anAttachVector.Magnitude(); |
1416 | |
1417 | // Add margin to ensure a small tail between text and arrow |
1418 | Standard_Real anArrowMargin = aDimensionAspect->IsText3d() |
1419 | ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN |
1420 | : 0.0; |
1421 | |
1422 | Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0; |
1423 | |
1424 | theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth; |
1425 | break; |
1426 | } |
1427 | } |
1428 | |
1429 | // Handle user-defined and automatic text placement |
1430 | switch (theHorizontalTextPos) |
1431 | { |
1432 | case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break; |
1433 | case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break; |
1434 | case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break; |
1435 | case Prs3d_DTHP_Fit: |
1436 | { |
1437 | gp_Vec anAttachVector (aFirstAttach, aSecondAttach); |
1438 | Standard_Real aDimensionWidth = anAttachVector.Magnitude(); |
1439 | Standard_Real anArrowsWidth = anArrowLength * 2.0; |
1440 | Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth; |
1441 | |
1442 | theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; |
1443 | break; |
1444 | } |
1445 | } |
1446 | |
1447 | switch (aDimensionAspect->TextVerticalPosition()) |
1448 | { |
1449 | case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break; |
1450 | case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break; |
1451 | case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break; |
1452 | } |
1453 | } |