60bf98ae |
1 | // Created on: 2013-11-11 |
2 | // Created by: Anastasia BORISOVA |
d5f74e42 |
3 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
a6eb515f |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
a6eb515f |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
a6eb515f |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
a6eb515f |
15 | |
787ff240 |
16 | #include <PrsDim_Dimension.hxx> |
d7bffd44 |
17 | |
787ff240 |
18 | #include <PrsDim.hxx> |
19 | #include <PrsDim_DimensionOwner.hxx> |
c22b52d6 |
20 | #include <Adaptor3d_Curve.hxx> |
a6eb515f |
21 | #include <BRepAdaptor_Curve.hxx> |
22 | #include <BRepAdaptor_Surface.hxx> |
a6eb515f |
23 | #include <BRepBndLib.hxx> |
60bf98ae |
24 | #include <Bnd_Box.hxx> |
a6eb515f |
25 | #include <ElCLib.hxx> |
26 | #include <Font_BRepFont.hxx> |
ac84fcf6 |
27 | #include <Font_BRepTextBuilder.hxx> |
a6eb515f |
28 | #include <GC_MakeCircle.hxx> |
af203d54 |
29 | #include <Geom_Line.hxx> |
fe83e1ea |
30 | #include <GeomAdaptor_Curve.hxx> |
a6eb515f |
31 | #include <Geom_TrimmedCurve.hxx> |
32 | #include <gce_MakeDir.hxx> |
33 | #include <gce_MakeLin.hxx> |
af203d54 |
34 | #include <gce_MakePln.hxx> |
a6eb515f |
35 | #include <Graphic3d_ArrayOfSegments.hxx> |
36 | #include <Graphic3d_ArrayOfTriangles.hxx> |
37 | #include <Graphic3d_AspectLine3d.hxx> |
38 | #include <Graphic3d_AspectFillArea3d.hxx> |
39 | #include <Graphic3d_AspectText3d.hxx> |
40 | #include <Graphic3d_Group.hxx> |
41 | #include <PrsMgr_PresentationManager3d.hxx> |
42 | #include <Prs3d_Arrow.hxx> |
43 | #include <Prs3d_ArrowAspect.hxx> |
44 | #include <Prs3d_Drawer.hxx> |
45 | #include <Prs3d_LineAspect.hxx> |
46 | #include <Prs3d_Presentation.hxx> |
a6eb515f |
47 | #include <Prs3d_ShadingAspect.hxx> |
48 | #include <Prs3d_Text.hxx> |
49 | #include <SelectMgr_EntityOwner.hxx> |
50 | #include <SelectMgr_Selection.hxx> |
51 | #include <SelectMgr_SequenceOfOwner.hxx> |
a6eb515f |
52 | #include <Select3D_SensitiveCircle.hxx> |
53 | #include <Select3D_SensitiveGroup.hxx> |
fe83e1ea |
54 | #include <Select3D_SensitiveCurve.hxx> |
a6eb515f |
55 | #include <Select3D_SensitiveSegment.hxx> |
fe83e1ea |
56 | #include <Select3D_SensitiveTriangle.hxx> |
51f8f60c |
57 | #include <Select3D_SensitiveTriangulation.hxx> |
58 | #include <Poly_Array1OfTriangle.hxx> |
59 | #include <Poly_Triangulation.hxx> |
a6eb515f |
60 | #include <Standard_CString.hxx> |
af203d54 |
61 | #include <Standard_ProgramError.hxx> |
a6eb515f |
62 | #include <StdPrs_ShadedShape.hxx> |
63 | #include <StdPrs_WFShape.hxx> |
64 | #include <TCollection_AsciiString.hxx> |
65 | #include <TCollection_ExtendedString.hxx> |
66 | #include <TopExp_Explorer.hxx> |
67 | #include <TopoDS.hxx> |
0499eb06 |
68 | #include <TopoDS_Edge.hxx> |
a6eb515f |
69 | #include <TopoDS_Vertex.hxx> |
70 | #include <Units.hxx> |
71 | #include <Units_UnitsDictionary.hxx> |
72 | #include <UnitsAPI.hxx> |
73 | #include <UnitsAPI_SystemUnits.hxx> |
74 | |
787ff240 |
75 | IMPLEMENT_STANDARD_RTTIEXT(PrsDim_Dimension, AIS_InteractiveObject) |
92efcf78 |
76 | |
d7bffd44 |
77 | namespace |
a6eb515f |
78 | { |
fe83e1ea |
79 | // default text strings |
d7bffd44 |
80 | static const TCollection_ExtendedString THE_EMPTY_LABEL; |
60bf98ae |
81 | static const TCollection_AsciiString THE_UNDEFINED_UNITS; |
fe83e1ea |
82 | |
83 | // default text margin and resolution |
84 | static const Standard_Real THE_3D_TEXT_MARGIN = 0.1; |
85 | static const unsigned int THE_2D_TEXT_RESOLUTION = 72; |
86 | |
87 | // default selection priorities |
88 | static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5; |
89 | static const Standard_Integer THE_LOCAL_SEL_PRIORITY = 6; |
a3f6f591 |
90 | } |
a6eb515f |
91 | |
92 | //======================================================================= |
93 | //function : Constructor |
94 | //purpose : |
95 | //======================================================================= |
787ff240 |
96 | PrsDim_Dimension::PrsDim_Dimension (const PrsDim_KindOfDimension theType) |
cbff1e55 |
97 | : AIS_InteractiveObject (), |
98 | mySelToleranceForText2d(0.0), |
73ddbb9a |
99 | myValueType (ValueType_Computed), |
cbff1e55 |
100 | myCustomValue (0.0), |
73ddbb9a |
101 | myCustomStringValue (), |
cbff1e55 |
102 | myIsTextPositionFixed (Standard_False), |
103 | mySpecialSymbol (' '), |
787ff240 |
104 | myDisplaySpecialSymbol (PrsDim_DisplaySpecialSymbol_No), |
cbff1e55 |
105 | myGeometryType (GeometryType_UndefShapes), |
106 | myIsPlaneCustom (Standard_False), |
107 | myFlyout (0.0), |
108 | myIsGeometryValid (Standard_False), |
109 | myKindOfDimension (theType) |
a6eb515f |
110 | { |
a6eb515f |
111 | } |
112 | |
113 | //======================================================================= |
60bf98ae |
114 | //function : SetCustomValue |
115 | //purpose : |
a6eb515f |
116 | //======================================================================= |
787ff240 |
117 | void PrsDim_Dimension::SetCustomValue (const Standard_Real theValue) |
a6eb515f |
118 | { |
73ddbb9a |
119 | if (myValueType == ValueType_CustomReal && myCustomValue == theValue) |
60bf98ae |
120 | { |
121 | return; |
122 | } |
a6eb515f |
123 | |
73ddbb9a |
124 | myValueType = ValueType_CustomReal; |
60bf98ae |
125 | myCustomValue = theValue; |
126 | |
127 | SetToUpdate(); |
a6eb515f |
128 | } |
129 | |
73ddbb9a |
130 | //======================================================================= |
131 | //function : SetCustomValue |
132 | //purpose : |
133 | //======================================================================= |
787ff240 |
134 | void PrsDim_Dimension::SetCustomValue (const TCollection_ExtendedString& theValue) |
73ddbb9a |
135 | { |
136 | if (myValueType == ValueType_CustomText && myCustomStringValue == theValue) |
137 | { |
138 | return; |
139 | } |
140 | |
141 | myValueType = ValueType_CustomText; |
142 | myCustomStringValue = theValue; |
143 | |
144 | SetToUpdate(); |
145 | } |
146 | |
a6eb515f |
147 | //======================================================================= |
60bf98ae |
148 | //function : SetUserPlane |
a6eb515f |
149 | //purpose : |
150 | //======================================================================= |
787ff240 |
151 | void PrsDim_Dimension::SetCustomPlane (const gp_Pln& thePlane) |
a6eb515f |
152 | { |
60bf98ae |
153 | myPlane = thePlane; |
154 | myIsPlaneCustom = Standard_True; |
155 | |
91b16a64 |
156 | // Disable fixed (custom) text position |
af203d54 |
157 | UnsetFixedTextPosition(); |
158 | |
60bf98ae |
159 | // Check validity if geometry has been set already. |
91b16a64 |
160 | if (IsValid()) |
60bf98ae |
161 | { |
60bf98ae |
162 | SetToUpdate(); |
163 | } |
a6eb515f |
164 | } |
165 | |
166 | //======================================================================= |
60bf98ae |
167 | //function : SetDimensionAspect |
168 | //purpose : |
a6eb515f |
169 | //======================================================================= |
787ff240 |
170 | void PrsDim_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect) |
a6eb515f |
171 | { |
60bf98ae |
172 | myDrawer->SetDimensionAspect (theDimensionAspect); |
173 | |
174 | SetToUpdate(); |
a6eb515f |
175 | } |
176 | |
177 | //======================================================================= |
60bf98ae |
178 | //function : SetDisplaySpecialSymbol |
179 | //purpose : |
a6eb515f |
180 | //======================================================================= |
787ff240 |
181 | void PrsDim_Dimension::SetDisplaySpecialSymbol (const PrsDim_DisplaySpecialSymbol theDisplaySpecSymbol) |
a6eb515f |
182 | { |
60bf98ae |
183 | if (myDisplaySpecialSymbol == theDisplaySpecSymbol) |
184 | { |
185 | return; |
186 | } |
187 | |
188 | myDisplaySpecialSymbol = theDisplaySpecSymbol; |
189 | |
190 | SetToUpdate(); |
a6eb515f |
191 | } |
192 | |
193 | //======================================================================= |
60bf98ae |
194 | //function : SetSpecialSymbol |
a6eb515f |
195 | //purpose : |
196 | //======================================================================= |
787ff240 |
197 | void PrsDim_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol) |
a6eb515f |
198 | { |
60bf98ae |
199 | if (mySpecialSymbol == theSpecialSymbol) |
200 | { |
201 | return; |
202 | } |
203 | |
204 | mySpecialSymbol = theSpecialSymbol; |
205 | |
206 | SetToUpdate(); |
a6eb515f |
207 | } |
208 | |
209 | //======================================================================= |
60bf98ae |
210 | //function : SetSelToleranceForText2d |
211 | //purpose : |
a6eb515f |
212 | //======================================================================= |
787ff240 |
213 | void PrsDim_Dimension::SetSelToleranceForText2d (const Standard_Real theTol) |
a6eb515f |
214 | { |
60bf98ae |
215 | if (mySelToleranceForText2d == theTol) |
216 | { |
217 | return; |
218 | } |
219 | |
220 | mySelToleranceForText2d = theTol; |
221 | |
222 | SetToUpdate(); |
a6eb515f |
223 | } |
224 | |
225 | //======================================================================= |
60bf98ae |
226 | //function : SetFlyout |
227 | //purpose : |
a6eb515f |
228 | //======================================================================= |
787ff240 |
229 | void PrsDim_Dimension::SetFlyout (const Standard_Real theFlyout) |
a6eb515f |
230 | { |
60bf98ae |
231 | if (myFlyout == theFlyout) |
232 | { |
233 | return; |
234 | } |
a6eb515f |
235 | |
60bf98ae |
236 | myFlyout = theFlyout; |
237 | |
af203d54 |
238 | // Disable fixed text position |
239 | UnsetFixedTextPosition(); |
240 | |
60bf98ae |
241 | SetToUpdate(); |
242 | } |
a6eb515f |
243 | |
244 | //======================================================================= |
60bf98ae |
245 | //function : GetDisplayUnits |
246 | //purpose : |
a6eb515f |
247 | //======================================================================= |
787ff240 |
248 | const TCollection_AsciiString& PrsDim_Dimension::GetDisplayUnits() const |
a6eb515f |
249 | { |
60bf98ae |
250 | return THE_UNDEFINED_UNITS; |
a6eb515f |
251 | } |
252 | |
253 | //======================================================================= |
60bf98ae |
254 | //function : GetModelUnits |
255 | //purpose : |
a6eb515f |
256 | //======================================================================= |
787ff240 |
257 | const TCollection_AsciiString& PrsDim_Dimension::GetModelUnits() const |
a6eb515f |
258 | { |
60bf98ae |
259 | return THE_UNDEFINED_UNITS; |
a6eb515f |
260 | } |
261 | |
262 | //======================================================================= |
60bf98ae |
263 | //function : ValueToDisplayUnits |
264 | //purpose : |
a6eb515f |
265 | //======================================================================= |
787ff240 |
266 | Standard_Real PrsDim_Dimension::ValueToDisplayUnits() const |
a6eb515f |
267 | { |
60bf98ae |
268 | return UnitsAPI::AnyToAny (GetValue(), |
269 | GetModelUnits().ToCString(), |
270 | GetDisplayUnits().ToCString()); |
a6eb515f |
271 | } |
272 | |
273 | //======================================================================= |
60bf98ae |
274 | //function : GetValueString |
a6eb515f |
275 | //purpose : |
276 | //======================================================================= |
787ff240 |
277 | TCollection_ExtendedString PrsDim_Dimension::GetValueString (Standard_Real& theWidth) const |
a6eb515f |
278 | { |
73ddbb9a |
279 | TCollection_ExtendedString aValueStr; |
280 | if (myValueType == ValueType_CustomText) |
281 | { |
282 | aValueStr = myCustomStringValue; |
283 | } |
284 | else |
285 | { |
286 | // format value string using "sprintf" |
287 | TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat(); |
a6eb515f |
288 | |
73ddbb9a |
289 | char aFmtBuffer[256]; |
290 | sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits()); |
291 | aValueStr = TCollection_ExtendedString (aFmtBuffer); |
292 | } |
a6eb515f |
293 | |
60bf98ae |
294 | // add units to values string |
295 | if (myDrawer->DimensionAspect()->IsUnitsDisplayed()) |
a6eb515f |
296 | { |
60bf98ae |
297 | aValueStr += " "; |
298 | aValueStr += TCollection_ExtendedString (GetDisplayUnits()); |
a6eb515f |
299 | } |
60bf98ae |
300 | |
301 | switch (myDisplaySpecialSymbol) |
a6eb515f |
302 | { |
787ff240 |
303 | case PrsDim_DisplaySpecialSymbol_Before: aValueStr.Insert (1, mySpecialSymbol); break; |
304 | case PrsDim_DisplaySpecialSymbol_After: aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break; |
305 | case PrsDim_DisplaySpecialSymbol_No: break; |
a6eb515f |
306 | } |
307 | |
d7bffd44 |
308 | // Get text style parameters |
b6472664 |
309 | Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect(); |
fb0b0531 |
310 | NCollection_Utf8String anUTFString (aValueStr.ToExtString()); |
fe83e1ea |
311 | |
d7bffd44 |
312 | theWidth = 0.0; |
fe83e1ea |
313 | |
314 | if (myDrawer->DimensionAspect()->IsText3d()) |
315 | { |
316 | // text width produced by BRepFont |
1bbd7c79 |
317 | Font_BRepFont aFont; |
318 | if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any)) |
fe83e1ea |
319 | { |
1bbd7c79 |
320 | for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) |
321 | { |
322 | Standard_Utf32Char aCurrChar = *anIter; |
323 | Standard_Utf32Char aNextChar = *(++anIter); |
324 | theWidth += aFont.AdvanceX (aCurrChar, aNextChar); |
325 | } |
fe83e1ea |
326 | } |
327 | } |
328 | else |
d7bffd44 |
329 | { |
fe83e1ea |
330 | // Text width for 1:1 scale 2D case |
1bbd7c79 |
331 | Font_FTFontParams aFontParams; |
332 | aFontParams.PointSize = (unsigned int )aTextAspect->Height(); |
333 | aFontParams.Resolution = THE_2D_TEXT_RESOLUTION; |
334 | if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aFontParams, Font_StrictLevel_Any)) |
fe83e1ea |
335 | { |
1bbd7c79 |
336 | for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) |
337 | { |
338 | Standard_Utf32Char aCurrChar = *anIter; |
339 | Standard_Utf32Char aNextChar = *(++anIter); |
340 | theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar); |
341 | } |
fe83e1ea |
342 | } |
d7bffd44 |
343 | } |
60bf98ae |
344 | |
345 | return aValueStr; |
a6eb515f |
346 | } |
347 | |
348 | //======================================================================= |
60bf98ae |
349 | //function : DrawArrow |
a6eb515f |
350 | //purpose : |
351 | //======================================================================= |
787ff240 |
352 | void PrsDim_Dimension::DrawArrow (const Handle(Prs3d_Presentation)& thePresentation, |
353 | const gp_Pnt& theLocation, |
354 | const gp_Dir& theDirection) |
a6eb515f |
355 | { |
d6c48921 |
356 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
fe83e1ea |
357 | |
ee2be2a8 |
358 | Standard_Real aLength = myDrawer->DimensionAspect()->ArrowAspect()->Length(); |
359 | Standard_Real anAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle(); |
a6eb515f |
360 | |
361 | if (myDrawer->DimensionAspect()->IsArrows3d()) |
362 | { |
4ad142d9 |
363 | Prs3d_Arrow::Draw (aGroup, |
a6eb515f |
364 | theLocation, |
d7bffd44 |
365 | theDirection, |
fe83e1ea |
366 | anAngle, |
367 | aLength); |
4ad142d9 |
368 | aGroup->SetGroupPrimitivesAspect (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()); |
a6eb515f |
369 | } |
370 | else |
371 | { |
fe83e1ea |
372 | gp_Pnt aLeftPoint (gp::Origin()); |
373 | gp_Pnt aRightPoint (gp::Origin()); |
60bf98ae |
374 | const gp_Dir& aPlane = GetPlane().Axis().Direction(); |
fe83e1ea |
375 | |
376 | PointsForArrow (theLocation, theDirection, aPlane, aLength, anAngle, aLeftPoint, aRightPoint); |
377 | |
a6eb515f |
378 | Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3); |
a6eb515f |
379 | |
380 | anArrow->AddVertex (aLeftPoint); |
381 | anArrow->AddVertex (theLocation); |
382 | anArrow->AddVertex (aRightPoint); |
383 | |
384 | // Set aspect for arrow triangles |
bbd8ce10 |
385 | Graphic3d_PolygonOffset aPolOffset; |
386 | aPolOffset.Mode = Aspect_POM_Off; |
387 | aPolOffset.Factor = 0.0f; |
388 | aPolOffset.Units = 0.0f; |
389 | Handle(Graphic3d_AspectFillArea3d) aShadingStyle = new Graphic3d_AspectFillArea3d(); |
390 | aShadingStyle->SetInteriorStyle (Aspect_IS_SOLID); |
b6472664 |
391 | aShadingStyle->SetColor (myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Color()); |
bbd8ce10 |
392 | aShadingStyle->SetShadingModel (Graphic3d_TOSM_UNLIT); |
393 | aShadingStyle->SetPolygonOffset (aPolOffset); |
d7bffd44 |
394 | |
bbd8ce10 |
395 | aGroup->SetPrimitivesAspect (aShadingStyle); |
4ad142d9 |
396 | aGroup->AddPrimitiveArray (anArrow); |
a6eb515f |
397 | } |
fe83e1ea |
398 | |
399 | SelectionGeometry::Arrow& aSensitiveArrow = mySelectionGeom.NewArrow(); |
400 | aSensitiveArrow.Position = theLocation; |
401 | aSensitiveArrow.Direction = theDirection; |
a6eb515f |
402 | } |
403 | |
404 | //======================================================================= |
7c65581d |
405 | //function : drawText |
406 | //purpose : |
a6eb515f |
407 | //======================================================================= |
787ff240 |
408 | void PrsDim_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation, |
409 | const gp_Pnt& theTextPos, |
410 | const gp_Dir& theTextDir, |
411 | const TCollection_ExtendedString& theText, |
412 | const Standard_Integer theLabelPosition) |
a6eb515f |
413 | { |
bf5f0ca2 |
414 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
a6eb515f |
415 | if (myDrawer->DimensionAspect()->IsText3d()) |
416 | { |
fe83e1ea |
417 | // getting font parameters |
b6472664 |
418 | Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect(); |
419 | Quantity_Color aColor = aTextAspect->Aspect()->Color(); |
420 | Font_FontAspect aFontAspect = aTextAspect->Aspect()->GetTextFontAspect(); |
421 | Standard_Real aFontHeight = aTextAspect->Height(); |
a6eb515f |
422 | |
fe83e1ea |
423 | // creating TopoDS_Shape for text |
b6472664 |
424 | Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(), |
425 | aFontAspect, aFontHeight); |
fb0b0531 |
426 | NCollection_Utf8String anUTFString (theText.ToExtString()); |
ac84fcf6 |
427 | |
428 | Font_BRepTextBuilder aBuilder; |
429 | TopoDS_Shape aTextShape = aBuilder.Perform (aFont, anUTFString); |
a6eb515f |
430 | |
fe83e1ea |
431 | // compute text width with kerning |
432 | Standard_Real aTextWidth = 0.0; |
433 | Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender(); |
d7bffd44 |
434 | |
fe83e1ea |
435 | for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) |
436 | { |
437 | Standard_Utf32Char aCurrChar = *anIter; |
438 | Standard_Utf32Char aNextChar = *(++anIter); |
439 | aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar); |
440 | } |
441 | |
442 | // formating text position in XOY plane |
d7bffd44 |
443 | Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask; |
444 | Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask; |
445 | |
446 | gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir); |
447 | |
448 | // compute label offsets |
fe83e1ea |
449 | Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN; |
d7bffd44 |
450 | Standard_Real aCenterHOffset = 0.0; |
451 | Standard_Real aCenterVOffset = 0.0; |
452 | switch (aHLabelPos) |
a6eb515f |
453 | { |
d7bffd44 |
454 | case LabelPosition_HCenter : aCenterHOffset = 0.0; break; |
455 | case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break; |
456 | case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break; |
a6eb515f |
457 | } |
d7bffd44 |
458 | switch (aVLabelPos) |
a6eb515f |
459 | { |
d7bffd44 |
460 | case LabelPosition_VCenter : aCenterVOffset = 0.0; break; |
461 | case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break; |
462 | case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break; |
a6eb515f |
463 | } |
d7bffd44 |
464 | |
465 | // compute shape offset transformation |
fe83e1ea |
466 | Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0; |
d7bffd44 |
467 | Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0; |
468 | |
fe83e1ea |
469 | // center shape in its bounding box (suppress border spacing added by FT_Font) |
470 | Bnd_Box aShapeBnd; |
471 | BRepBndLib::AddClose (aTextShape, aShapeBnd); |
472 | |
473 | Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; |
474 | aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); |
475 | |
476 | Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5; |
477 | Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5; |
478 | aShapeHOffset += aXalign; |
479 | aShapeVOffset += aYalign; |
480 | |
d7bffd44 |
481 | gp_Trsf anOffsetTrsf; |
482 | anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0)); |
483 | aTextShape.Move (anOffsetTrsf); |
a6eb515f |
484 | |
fe83e1ea |
485 | // transform text to myWorkingPlane coordinate system |
60bf98ae |
486 | gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir); |
d7bffd44 |
487 | gp_Trsf aTextPlaneTrsf; |
488 | aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY())); |
489 | aTextShape.Move (aTextPlaneTrsf); |
a6eb515f |
490 | |
fe83e1ea |
491 | // set text flipping anchors |
d7bffd44 |
492 | gp_Trsf aCenterOffsetTrsf; |
493 | gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0); |
494 | aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset); |
495 | |
fe83e1ea |
496 | gp_Pnt aCenterOfLabel (gp::Origin()); |
497 | aCenterOfLabel.Transform (aCenterOffsetTrsf); |
498 | aCenterOfLabel.Transform (aTextPlaneTrsf); |
d7bffd44 |
499 | |
60bf98ae |
500 | gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir); |
bf5f0ca2 |
501 | aGroup->SetFlippingOptions (Standard_True, aFlippingAxes); |
d7bffd44 |
502 | |
fe83e1ea |
503 | // draw text |
a6eb515f |
504 | if (myDrawer->DimensionAspect()->IsTextShaded()) |
505 | { |
506 | // Setting text shading and color parameters |
d2dfbc4d |
507 | if (!myDrawer->HasOwnShadingAspect()) |
508 | { |
509 | myDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); |
510 | } |
511 | |
a966542b |
512 | Graphic3d_MaterialAspect aShadeMat (Graphic3d_NameOfMaterial_DEFAULT); |
61168418 |
513 | aShadeMat.SetAmbientColor (Quantity_NOC_BLACK); |
514 | aShadeMat.SetDiffuseColor (Quantity_NOC_BLACK); |
515 | aShadeMat.SetSpecularColor(Quantity_NOC_BLACK); |
a6eb515f |
516 | myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor); |
517 | myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor); |
518 | myDrawer->ShadingAspect()->SetMaterial (aShadeMat); |
519 | |
fe83e1ea |
520 | // drawing text |
a6eb515f |
521 | StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer); |
522 | } |
523 | else |
524 | { |
d2dfbc4d |
525 | // Setting color for text |
526 | if (!myDrawer->HasOwnFreeBoundaryAspect()) |
527 | { |
528 | myDrawer->SetFreeBoundaryAspect (new Prs3d_LineAspect (aColor, Aspect_TOL_SOLID, 1.0)); |
529 | } |
a6eb515f |
530 | myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor); |
d2dfbc4d |
531 | |
fe83e1ea |
532 | // drawing text |
bf5f0ca2 |
533 | if (Handle(Graphic3d_ArrayOfPrimitives) anEdges = StdPrs_WFShape::AddAllEdges (aTextShape, myDrawer)) |
534 | { |
535 | aGroup->SetGroupPrimitivesAspect (myDrawer->FreeBoundaryAspect()->Aspect()); |
536 | aGroup->AddPrimitiveArray (anEdges); |
537 | } |
a6eb515f |
538 | } |
d6c48921 |
539 | thePresentation->CurrentGroup()->SetFlippingOptions (Standard_False, gp_Ax2()); |
d7bffd44 |
540 | |
fe83e1ea |
541 | mySelectionGeom.TextPos = aCenterOfLabel; |
542 | mySelectionGeom.TextDir = aTextDir; |
543 | mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0; |
544 | mySelectionGeom.TextHeight = aTextHeight; |
545 | |
546 | return; |
a6eb515f |
547 | } |
548 | |
fe83e1ea |
549 | // generate primitives for 2D text |
d7bffd44 |
550 | myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION); |
551 | |
bf5f0ca2 |
552 | Prs3d_Text::Draw (aGroup, |
d7bffd44 |
553 | myDrawer->DimensionAspect()->TextAspect(), |
554 | theText, |
fe83e1ea |
555 | theTextPos); |
d7bffd44 |
556 | |
fe83e1ea |
557 | mySelectionGeom.TextPos = theTextPos; |
558 | mySelectionGeom.TextDir = theTextDir; |
559 | mySelectionGeom.TextWidth = 0.0; |
560 | mySelectionGeom.TextHeight = 0.0; |
a6eb515f |
561 | } |
562 | |
d7bffd44 |
563 | //======================================================================= |
60bf98ae |
564 | //function : DrawExtension |
a6eb515f |
565 | //purpose : |
566 | //======================================================================= |
787ff240 |
567 | void PrsDim_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresentation, |
568 | const Standard_Real theExtensionSize, |
569 | const gp_Pnt& theExtensionStart, |
570 | const gp_Dir& theExtensionDir, |
571 | const TCollection_ExtendedString& theLabelString, |
572 | const Standard_Real theLabelWidth, |
573 | const Standard_Integer theMode, |
574 | const Standard_Integer theLabelPosition) |
a6eb515f |
575 | { |
fe83e1ea |
576 | // reference line for extension starting at its connection point |
577 | gp_Lin anExtensionLine (theExtensionStart, theExtensionDir); |
a6eb515f |
578 | |
fe83e1ea |
579 | Standard_Boolean hasLabel = theLabelString.Length() > 0; |
fe83e1ea |
580 | if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text)) |
a6eb515f |
581 | { |
d7bffd44 |
582 | // compute text primitives; get its model width |
fe83e1ea |
583 | gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine); |
60bf98ae |
584 | gp_Dir aTextDir = theExtensionDir; |
fe83e1ea |
585 | |
bf5f0ca2 |
586 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
7c65581d |
587 | drawText (thePresentation, |
fe83e1ea |
588 | aTextPos, |
589 | aTextDir, |
590 | theLabelString, |
591 | theLabelPosition); |
a6eb515f |
592 | } |
593 | |
fe83e1ea |
594 | if (theMode != ComputeMode_All && theMode != ComputeMode_Line) |
a6eb515f |
595 | { |
d7bffd44 |
596 | return; |
a6eb515f |
597 | } |
598 | |
fe83e1ea |
599 | Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d() |
600 | || theLabelPosition & LabelPosition_VCenter; |
601 | |
d7bffd44 |
602 | // compute graphical primitives and sensitives for extension line |
603 | gp_Pnt anExtStart = theExtensionStart; |
fe83e1ea |
604 | gp_Pnt anExtEnd = !hasLabel || isShortLine |
605 | ? ElCLib::Value (theExtensionSize, anExtensionLine) |
606 | : ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine); |
d7bffd44 |
607 | |
fe83e1ea |
608 | // add graphical primitives |
d7bffd44 |
609 | Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2); |
610 | anExtPrimitive->AddVertex (anExtStart); |
611 | anExtPrimitive->AddVertex (anExtEnd); |
612 | |
fe83e1ea |
613 | // add selection primitives |
614 | SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve(); |
615 | aSensitiveCurve.Append (anExtStart); |
616 | aSensitiveCurve.Append (anExtEnd); |
a6eb515f |
617 | |
bf5f0ca2 |
618 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
fe83e1ea |
619 | if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All) |
a6eb515f |
620 | { |
bf5f0ca2 |
621 | aGroup->SetStencilTestOptions (Standard_True); |
d7bffd44 |
622 | } |
623 | Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect(); |
bf5f0ca2 |
624 | aGroup->SetPrimitivesAspect (aDimensionLineStyle); |
625 | aGroup->AddPrimitiveArray (anExtPrimitive); |
fe83e1ea |
626 | if (!myDrawer->DimensionAspect()->IsText3d() && theMode == ComputeMode_All) |
d7bffd44 |
627 | { |
bf5f0ca2 |
628 | aGroup->SetStencilTestOptions (Standard_False); |
a6eb515f |
629 | } |
630 | } |
631 | |
632 | //======================================================================= |
60bf98ae |
633 | //function : DrawLinearDimension |
a6eb515f |
634 | //purpose : |
635 | //======================================================================= |
787ff240 |
636 | void PrsDim_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation, |
637 | const Standard_Integer theMode, |
638 | const gp_Pnt& theFirstPoint, |
639 | const gp_Pnt& theSecondPoint, |
640 | const Standard_Boolean theIsOneSide) |
a6eb515f |
641 | { |
60bf98ae |
642 | // do not build any dimension for equal points |
643 | if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion())) |
a6eb515f |
644 | { |
9775fa61 |
645 | throw Standard_ProgramError("Can not build presentation for equal points."); |
a6eb515f |
646 | } |
d7bffd44 |
647 | |
a6eb515f |
648 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
a6eb515f |
649 | |
d7bffd44 |
650 | // For extensions we need to know arrow size, text size and extension size: get it from aspect |
ee2be2a8 |
651 | Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
652 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
fe83e1ea |
653 | // prepare label string and compute its geometrical width |
654 | Standard_Real aLabelWidth; |
60bf98ae |
655 | TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); |
a6eb515f |
656 | |
fe83e1ea |
657 | // add margins to cut dimension lines for 3d text |
658 | if (aDimensionAspect->IsText3d()) |
659 | { |
660 | aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; |
661 | } |
662 | |
663 | // handle user-defined and automatic arrow placement |
af203d54 |
664 | Standard_Boolean isArrowsExternal = Standard_False; |
665 | Standard_Integer aLabelPosition = LabelPosition_None; |
fe83e1ea |
666 | |
af203d54 |
667 | Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition(); |
668 | if (IsTextPositionCustom()) |
669 | { |
91b16a64 |
670 | if (!AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint, |
671 | anExtensionSize, aHorisontalTextPos, myFlyout, myPlane, myIsPlaneCustom)) |
672 | { |
9775fa61 |
673 | throw Standard_ProgramError("Can not adjust plane to the custom label position."); |
91b16a64 |
674 | } |
a6eb515f |
675 | } |
a6eb515f |
676 | |
af203d54 |
677 | FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos, |
678 | aLabelPosition, isArrowsExternal); |
679 | |
948c552a |
680 | // compute dimension line points |
681 | gp_Pnt aLineBegPoint, aLineEndPoint; |
682 | ComputeFlyoutLinePoints (theFirstPoint, theSecondPoint, aLineBegPoint, aLineEndPoint); |
af203d54 |
683 | gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint); |
684 | |
fe83e1ea |
685 | // compute arrows positions and directions |
d7bffd44 |
686 | gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed(); |
687 | gp_Dir aSecondArrowDir = aDimensionLine.Direction(); |
688 | gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed(); |
689 | gp_Dir aSecondExtensionDir = aDimensionLine.Direction(); |
690 | |
691 | gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0); |
692 | gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0); |
693 | gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0); |
694 | gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0); |
a6eb515f |
695 | |
d7bffd44 |
696 | if (isArrowsExternal) |
a6eb515f |
697 | { |
698 | aFirstArrowDir.Reverse(); |
699 | aSecondArrowDir.Reverse(); |
a6eb515f |
700 | } |
d7bffd44 |
701 | |
702 | aFirstArrowBegin = aLineBegPoint; |
703 | aSecondArrowBegin = aLineEndPoint; |
704 | aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength)); |
705 | aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength)); |
706 | |
707 | gp_Pnt aCenterLineBegin = isArrowsExternal |
60bf98ae |
708 | ? aLineBegPoint : aFirstArrowEnd; |
d7bffd44 |
709 | |
60bf98ae |
710 | gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide |
d7bffd44 |
711 | ? aLineEndPoint : aSecondArrowEnd; |
712 | |
a6eb515f |
713 | |
d7bffd44 |
714 | switch (aLabelPosition & LabelPosition_HMask) |
a6eb515f |
715 | { |
d7bffd44 |
716 | // ------------------------------------------------------------------------ // |
717 | // CENTER // |
718 | // -------------------------------------------------------------------------// |
d7bffd44 |
719 | case LabelPosition_HCenter: |
a6eb515f |
720 | { |
d7bffd44 |
721 | // add label on dimension or extension line to presentation |
af203d54 |
722 | gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition |
723 | : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5; |
60bf98ae |
724 | gp_Dir aTextDir = aDimensionLine.Direction(); |
a6eb515f |
725 | |
fe83e1ea |
726 | // add text primitives |
727 | if (theMode == ComputeMode_All || theMode == ComputeMode_Text) |
a6eb515f |
728 | { |
bf5f0ca2 |
729 | thePresentation->NewGroup(); |
7c65581d |
730 | drawText (thePresentation, |
fe83e1ea |
731 | aTextPos, |
732 | aTextDir, |
733 | aLabelString, |
734 | aLabelPosition); |
a6eb515f |
735 | } |
d7bffd44 |
736 | |
fe83e1ea |
737 | // add dimension line primitives |
738 | if (theMode == ComputeMode_All || theMode == ComputeMode_Line) |
739 | { |
740 | Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center |
741 | && aDimensionAspect->IsText3d(); |
d7bffd44 |
742 | |
fe83e1ea |
743 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2); |
d7bffd44 |
744 | |
fe83e1ea |
745 | // compute continuous or sectioned main line segments |
746 | if (isLineBreak) |
747 | { |
748 | Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, aTextPos); |
749 | gp_Pnt aSection1Beg = aCenterLineBegin; |
750 | gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - (aLabelWidth * 0.5), aDimensionLine); |
751 | gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + (aLabelWidth * 0.5), aDimensionLine); |
752 | gp_Pnt aSection2End = aCenterLineEnd; |
753 | |
754 | aPrimSegments->AddVertex (aSection1Beg); |
755 | aPrimSegments->AddVertex (aSection1End); |
756 | aPrimSegments->AddVertex (aSection2Beg); |
757 | aPrimSegments->AddVertex (aSection2End); |
758 | |
759 | SelectionGeometry::Curve& aLeftSensitiveCurve = mySelectionGeom.NewCurve(); |
760 | SelectionGeometry::Curve& aRightSensitiveCurve = mySelectionGeom.NewCurve(); |
761 | aLeftSensitiveCurve.Append (aSection1Beg); |
762 | aLeftSensitiveCurve.Append (aSection1End); |
763 | aRightSensitiveCurve.Append (aSection2Beg); |
764 | aRightSensitiveCurve.Append (aSection2End); |
765 | } |
766 | else |
767 | { |
768 | aPrimSegments->AddVertex (aCenterLineBegin); |
769 | aPrimSegments->AddVertex (aCenterLineEnd); |
a6eb515f |
770 | |
fe83e1ea |
771 | SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve(); |
772 | aSensitiveCurve.Append (aCenterLineBegin); |
773 | aSensitiveCurve.Append (aCenterLineEnd); |
774 | } |
a6eb515f |
775 | |
fe83e1ea |
776 | // set text label justification |
777 | Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM; |
778 | switch (aLabelPosition & LabelPosition_VMask) |
779 | { |
780 | case LabelPosition_Above : |
781 | case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break; |
782 | case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break; |
783 | } |
784 | aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton); |
a6eb515f |
785 | |
fe83e1ea |
786 | // main dimension line, short extension |
fe83e1ea |
787 | { |
bf5f0ca2 |
788 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
789 | if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All) |
790 | { |
791 | aGroup->SetStencilTestOptions (Standard_True); |
792 | } |
793 | aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
794 | aGroup->AddPrimitiveArray (aPrimSegments); |
795 | if (!aDimensionAspect->IsText3d() && theMode == ComputeMode_All) |
796 | { |
797 | aGroup->SetStencilTestOptions (Standard_False); |
798 | } |
fe83e1ea |
799 | } |
d7bffd44 |
800 | |
fe83e1ea |
801 | // add arrows to presentation |
fe83e1ea |
802 | { |
bf5f0ca2 |
803 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
804 | DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir); |
805 | if (!theIsOneSide) |
806 | { |
807 | DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir); |
808 | } |
fe83e1ea |
809 | } |
d7bffd44 |
810 | |
fe83e1ea |
811 | if (!isArrowsExternal) |
812 | { |
813 | break; |
814 | } |
d7bffd44 |
815 | |
fe83e1ea |
816 | // add arrow extension lines to presentation |
fe83e1ea |
817 | { |
af203d54 |
818 | DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), |
bf5f0ca2 |
819 | aFirstArrowEnd, aFirstExtensionDir, |
fe83e1ea |
820 | THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); |
bf5f0ca2 |
821 | if (!theIsOneSide) |
822 | { |
823 | DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), |
824 | aSecondArrowEnd, aSecondExtensionDir, |
825 | THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); |
826 | } |
fe83e1ea |
827 | } |
a6eb515f |
828 | } |
1d7ca641 |
829 | break; |
a6eb515f |
830 | } |
d7bffd44 |
831 | // ------------------------------------------------------------------------ // |
832 | // LEFT // |
833 | // -------------------------------------------------------------------------// |
834 | |
835 | case LabelPosition_Left: |
a6eb515f |
836 | { |
d7bffd44 |
837 | // add label on dimension or extension line to presentation |
bf5f0ca2 |
838 | { |
839 | // Left extension with the text |
840 | DrawExtension (thePresentation, anExtensionSize, |
841 | isArrowsExternal |
842 | ? aFirstArrowEnd |
843 | : aFirstArrowBegin, |
844 | aFirstExtensionDir, |
845 | aLabelString, |
846 | aLabelWidth, |
847 | theMode, |
848 | aLabelPosition); |
849 | } |
d7bffd44 |
850 | |
fe83e1ea |
851 | // add dimension line primitives |
852 | if (theMode == ComputeMode_All || theMode == ComputeMode_Line) |
d7bffd44 |
853 | { |
fe83e1ea |
854 | // add central dimension line |
bf5f0ca2 |
855 | { |
856 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
d7bffd44 |
857 | |
bf5f0ca2 |
858 | // add graphical primitives |
859 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2); |
860 | aPrimSegments->AddVertex (aCenterLineBegin); |
861 | aPrimSegments->AddVertex (aCenterLineEnd); |
d7bffd44 |
862 | |
bf5f0ca2 |
863 | aGroup->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
864 | aGroup->AddPrimitiveArray (aPrimSegments); |
d7bffd44 |
865 | |
bf5f0ca2 |
866 | // add selection primitives |
867 | SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve(); |
868 | aSensitiveCurve.Append (aCenterLineBegin); |
869 | aSensitiveCurve.Append (aCenterLineEnd); |
870 | } |
a6eb515f |
871 | |
fe83e1ea |
872 | // add arrows to presentation |
fe83e1ea |
873 | { |
bf5f0ca2 |
874 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
875 | DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir); |
876 | if (!theIsOneSide) |
877 | { |
878 | DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir); |
879 | } |
fe83e1ea |
880 | } |
d7bffd44 |
881 | |
60bf98ae |
882 | if (!isArrowsExternal || theIsOneSide) |
fe83e1ea |
883 | { |
884 | break; |
885 | } |
d7bffd44 |
886 | |
fe83e1ea |
887 | // add extension lines for external arrows |
bf5f0ca2 |
888 | { |
889 | DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), |
890 | aSecondArrowEnd, aSecondExtensionDir, |
891 | THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); |
892 | } |
fe83e1ea |
893 | } |
d7bffd44 |
894 | |
a6eb515f |
895 | break; |
896 | } |
d7bffd44 |
897 | // ------------------------------------------------------------------------ // |
898 | // RIGHT // |
899 | // -------------------------------------------------------------------------// |
900 | |
901 | case LabelPosition_Right: |
a6eb515f |
902 | { |
d7bffd44 |
903 | // add label on dimension or extension line to presentation |
d7bffd44 |
904 | |
905 | // Right extension with text |
60bf98ae |
906 | DrawExtension (thePresentation, anExtensionSize, |
907 | isArrowsExternal |
908 | ? aSecondArrowEnd |
909 | : aSecondArrowBegin, |
d7bffd44 |
910 | aSecondExtensionDir, |
fe83e1ea |
911 | aLabelString, aLabelWidth, |
d7bffd44 |
912 | theMode, |
913 | aLabelPosition); |
914 | |
fe83e1ea |
915 | if (theMode == ComputeMode_All || theMode == ComputeMode_Line) |
a6eb515f |
916 | { |
fe83e1ea |
917 | // add central dimension line |
bf5f0ca2 |
918 | { |
919 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
a6eb515f |
920 | |
bf5f0ca2 |
921 | // add graphical primitives |
922 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2); |
923 | aPrimSegments->AddVertex (aCenterLineBegin); |
924 | aPrimSegments->AddVertex (aCenterLineEnd); |
925 | aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
926 | aGroup->AddPrimitiveArray (aPrimSegments); |
a6eb515f |
927 | |
bf5f0ca2 |
928 | // add selection primitives |
929 | SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve(); |
930 | aSensitiveCurve.Append (aCenterLineBegin); |
931 | aSensitiveCurve.Append (aCenterLineEnd); |
932 | } |
a6eb515f |
933 | |
fe83e1ea |
934 | // add arrows to presentation |
fe83e1ea |
935 | { |
bf5f0ca2 |
936 | thePresentation->NewGroup(); |
937 | DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir); |
938 | if (!theIsOneSide) |
939 | { |
940 | DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir); |
941 | } |
fe83e1ea |
942 | } |
d7bffd44 |
943 | |
60bf98ae |
944 | if (!isArrowsExternal || theIsOneSide) |
fe83e1ea |
945 | { |
946 | break; |
947 | } |
a6eb515f |
948 | |
fe83e1ea |
949 | // add extension lines for external arrows |
bf5f0ca2 |
950 | { |
951 | DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), |
952 | aFirstArrowEnd, aFirstExtensionDir, |
953 | THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); |
954 | } |
fe83e1ea |
955 | } |
d7bffd44 |
956 | |
a6eb515f |
957 | break; |
958 | } |
959 | } |
960 | |
d7bffd44 |
961 | // add flyout lines to presentation |
fe83e1ea |
962 | if (theMode == ComputeMode_All) |
d7bffd44 |
963 | { |
bf5f0ca2 |
964 | Handle(Graphic3d_Group) aGroup = thePresentation->NewGroup(); |
d7bffd44 |
965 | |
966 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4); |
60bf98ae |
967 | aPrimSegments->AddVertex (theFirstPoint); |
d7bffd44 |
968 | aPrimSegments->AddVertex (aLineBegPoint); |
969 | |
60bf98ae |
970 | aPrimSegments->AddVertex (theSecondPoint); |
d7bffd44 |
971 | aPrimSegments->AddVertex (aLineEndPoint); |
972 | |
bf5f0ca2 |
973 | aGroup->SetGroupPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
974 | aGroup->AddPrimitiveArray (aPrimSegments); |
d7bffd44 |
975 | } |
976 | |
91b16a64 |
977 | mySelectionGeom.IsComputed = Standard_True; |
a6eb515f |
978 | } |
979 | |
948c552a |
980 | //======================================================================= |
981 | //function : ComputeFlyoutLinePoints |
982 | //purpose : |
983 | //======================================================================= |
787ff240 |
984 | void PrsDim_Dimension::ComputeFlyoutLinePoints (const gp_Pnt& theFirstPoint, const gp_Pnt& theSecondPoint, |
985 | gp_Pnt& theLineBegPoint, gp_Pnt& theLineEndPoint) |
948c552a |
986 | { |
987 | // compute dimension line points |
988 | gp_Ax1 aPlaneNormal = GetPlane().Axis(); |
989 | // compute flyout direction vector |
990 | gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint); |
991 | gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector; |
992 | // create lines for layouts |
993 | gp_Lin aLine1 (theFirstPoint, aFlyoutVector); |
994 | gp_Lin aLine2 (theSecondPoint, aFlyoutVector); |
995 | |
996 | // Get flyout end points |
997 | theLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); |
998 | theLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); |
999 | } |
1000 | |
a6eb515f |
1001 | //======================================================================= |
60bf98ae |
1002 | //function : ComputeLinearFlyouts |
1003 | //purpose : |
a6eb515f |
1004 | //======================================================================= |
787ff240 |
1005 | void PrsDim_Dimension::ComputeLinearFlyouts (const Handle(SelectMgr_Selection)& theSelection, |
1006 | const Handle(SelectMgr_EntityOwner)& theOwner, |
1007 | const gp_Pnt& theFirstPoint, |
1008 | const gp_Pnt& theSecondPoint) |
a6eb515f |
1009 | { |
60bf98ae |
1010 | // count flyout direction |
1011 | gp_Ax1 aPlaneNormal = GetPlane().Axis(); |
1012 | gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint); |
a6eb515f |
1013 | |
60bf98ae |
1014 | // count a flyout direction vector. |
1015 | gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector; |
a6eb515f |
1016 | |
60bf98ae |
1017 | // create lines for layouts |
1018 | gp_Lin aLine1 (theFirstPoint, aFlyoutVector); |
1019 | gp_Lin aLine2 (theSecondPoint, aFlyoutVector); |
1020 | |
1021 | // get flyout end points |
1022 | gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); |
1023 | gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); |
1024 | |
1025 | // fill sensitive entity for flyouts |
1026 | Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner); |
1027 | aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theFirstPoint, aFlyoutEnd1)); |
1028 | aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, theSecondPoint, aFlyoutEnd2)); |
1029 | theSelection->Add (aSensitiveEntity); |
a6eb515f |
1030 | } |
1031 | |
1032 | //======================================================================= |
60bf98ae |
1033 | //function : CircleFromPlanarFace |
a6eb515f |
1034 | //purpose : if possible computes circle from planar face |
1035 | //======================================================================= |
787ff240 |
1036 | Standard_Boolean PrsDim_Dimension::CircleFromPlanarFace (const TopoDS_Face& theFace, |
1037 | Handle(Geom_Curve)& theCurve, |
1038 | gp_Pnt& theFirstPoint, |
1039 | gp_Pnt& theLastPoint) |
a6eb515f |
1040 | { |
1041 | TopExp_Explorer anIt (theFace, TopAbs_EDGE); |
1042 | for ( ; anIt.More(); anIt.Next()) |
1043 | { |
1044 | TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current()); |
787ff240 |
1045 | if (PrsDim::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint)) |
a6eb515f |
1046 | { |
1047 | if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle))) |
1048 | { |
1049 | return Standard_True; |
1050 | } |
1051 | } |
1052 | } |
1053 | return Standard_False; |
1054 | } |
1055 | |
0499eb06 |
1056 | //======================================================================= |
1057 | //function : CircleFromEdge |
1058 | //purpose : if possible computes circle from edge |
1059 | //======================================================================= |
787ff240 |
1060 | Standard_Boolean PrsDim_Dimension::CircleFromEdge (const TopoDS_Edge& theEdge, |
1061 | gp_Circ& theCircle, |
1062 | gp_Pnt& theFirstPoint, |
1063 | gp_Pnt& theLastPoint) |
0499eb06 |
1064 | { |
1065 | BRepAdaptor_Curve anAdaptedCurve (theEdge); |
1066 | switch (anAdaptedCurve.GetType()) |
1067 | { |
1068 | case GeomAbs_Circle: |
1069 | { |
1070 | theCircle = anAdaptedCurve.Circle(); |
1071 | break; |
1072 | } |
1073 | case GeomAbs_Ellipse: |
1074 | { |
1075 | gp_Elips anEll = anAdaptedCurve.Ellipse(); |
1076 | if ((anEll.MinorRadius() - anEll.MajorRadius()) >= Precision::Confusion()) |
1077 | { |
1078 | return Standard_False; |
1079 | } |
1080 | theCircle = gp_Circ(anEll.Position(),anEll.MinorRadius()); |
1081 | break; |
1082 | } |
1083 | case GeomAbs_Line: |
1084 | case GeomAbs_Hyperbola: |
1085 | case GeomAbs_Parabola: |
1086 | case GeomAbs_BezierCurve: |
1087 | case GeomAbs_BSplineCurve: |
1088 | case GeomAbs_OtherCurve: |
1089 | default: |
1090 | return Standard_False; |
1091 | } |
1092 | |
1093 | theFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter()); |
1094 | theLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter()); |
1095 | return Standard_True; |
1096 | } |
1097 | |
a6eb515f |
1098 | //======================================================================= |
60bf98ae |
1099 | //function : InitCircularDimension |
1100 | //purpose : |
a6eb515f |
1101 | //======================================================================= |
787ff240 |
1102 | Standard_Boolean PrsDim_Dimension::InitCircularDimension (const TopoDS_Shape& theShape, |
1103 | gp_Circ& theCircle, |
1104 | gp_Pnt& theMiddleArcPoint, |
1105 | Standard_Boolean& theIsClosed) |
a6eb515f |
1106 | { |
1107 | gp_Pln aPln; |
1108 | Handle(Geom_Surface) aBasisSurf; |
787ff240 |
1109 | PrsDim_KindOfSurface aSurfType = PrsDim_KOS_OtherSurface; |
a6eb515f |
1110 | gp_Pnt aFirstPoint, aLastPoint; |
1111 | Standard_Real anOffset = 0.0; |
1112 | Standard_Real aFirstParam = 0.0; |
1113 | Standard_Real aLastParam = 0.0; |
a6eb515f |
1114 | |
0499eb06 |
1115 | // Discover circular geometry |
1116 | switch (theShape.ShapeType()) |
a6eb515f |
1117 | { |
0499eb06 |
1118 | case TopAbs_FACE: |
a6eb515f |
1119 | { |
787ff240 |
1120 | PrsDim::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset); |
a6eb515f |
1121 | |
787ff240 |
1122 | if (aSurfType == PrsDim_KOS_Plane) |
a6eb515f |
1123 | { |
0499eb06 |
1124 | Handle(Geom_Curve) aCurve; |
1125 | if (!CircleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint)) |
1126 | { |
1127 | return Standard_False; |
1128 | } |
1129 | |
1130 | theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); |
a6eb515f |
1131 | } |
1132 | else |
1133 | { |
0499eb06 |
1134 | gp_Pnt aCurPos; |
1135 | BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape)); |
1136 | Standard_Real aFirstU = aSurf1.FirstUParameter(); |
1137 | Standard_Real aLastU = aSurf1.LastUParameter(); |
1138 | Standard_Real aFirstV = aSurf1.FirstVParameter(); |
1139 | Standard_Real aLastV = aSurf1.LastVParameter(); |
1140 | Standard_Real aMidU = (aFirstU + aLastU) * 0.5; |
1141 | Standard_Real aMidV = (aFirstV + aLastV) * 0.5; |
1142 | aSurf1.D0 (aMidU, aMidV, aCurPos); |
c22b52d6 |
1143 | Handle (Adaptor3d_Curve) aBasisCurve; |
0499eb06 |
1144 | Standard_Boolean isExpectedType = Standard_False; |
787ff240 |
1145 | if (aSurfType == PrsDim_KOS_Cylinder) |
a6eb515f |
1146 | { |
0499eb06 |
1147 | isExpectedType = Standard_True; |
a6eb515f |
1148 | } |
0499eb06 |
1149 | else |
a6eb515f |
1150 | { |
787ff240 |
1151 | if (aSurfType == PrsDim_KOS_Revolution) |
a6eb515f |
1152 | { |
0499eb06 |
1153 | aBasisCurve = aSurf1.BasisCurve(); |
1154 | if (aBasisCurve->GetType() == GeomAbs_Line) |
1155 | { |
1156 | isExpectedType = Standard_True; |
1157 | } |
1158 | } |
787ff240 |
1159 | else if (aSurfType == PrsDim_KOS_Extrusion) |
0499eb06 |
1160 | { |
1161 | aBasisCurve = aSurf1.BasisCurve(); |
1162 | if (aBasisCurve->GetType() == GeomAbs_Circle) |
1163 | { |
1164 | isExpectedType = Standard_True; |
1165 | } |
a6eb515f |
1166 | } |
1167 | } |
a6eb515f |
1168 | |
0499eb06 |
1169 | if (!isExpectedType) |
1170 | { |
1171 | return Standard_False; |
1172 | } |
60bf98ae |
1173 | |
0499eb06 |
1174 | Handle(Geom_Curve) aCurve = aBasisSurf->VIso(aMidV); |
1175 | if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle)) |
a6eb515f |
1176 | { |
0499eb06 |
1177 | theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); |
1178 | } |
1179 | else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve)) |
1180 | { |
1181 | Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve); |
1182 | aFirstU = aTrimmedCurve->FirstParameter(); |
1183 | aLastU = aTrimmedCurve->LastParameter(); |
1184 | if (aTrimmedCurve->BasisCurve()->DynamicType() == STANDARD_TYPE (Geom_Circle)) |
1185 | { |
1186 | theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve->BasisCurve())->Circ(); |
1187 | } |
1188 | } |
1189 | else |
1190 | { |
1191 | // Compute a circle from 3 points on "aCurve" |
1192 | gp_Pnt aP1, aP2; |
1193 | aSurf1.D0 (aFirstU, aMidV, aP1); |
1194 | aSurf1.D0 (aLastU, aMidV, aP2); |
1195 | GC_MakeCircle aMkCirc (aP1, aCurPos, aP2); |
1196 | theCircle = aMkCirc.Value()->Circ(); |
a6eb515f |
1197 | } |
a6eb515f |
1198 | |
0499eb06 |
1199 | aFirstPoint = ElCLib::Value (aFirstU, theCircle); |
1200 | aLastPoint = ElCLib::Value (aLastU, theCircle); |
1201 | } |
1202 | break; |
a6eb515f |
1203 | } |
0499eb06 |
1204 | case TopAbs_WIRE: |
a6eb515f |
1205 | { |
0499eb06 |
1206 | TopoDS_Edge anEdge; |
a6eb515f |
1207 | TopExp_Explorer anIt (theShape, TopAbs_EDGE); |
1208 | if (anIt.More()) |
1209 | { |
1210 | anEdge = TopoDS::Edge (anIt.Current()); |
1211 | } |
787ff240 |
1212 | if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint)) |
0499eb06 |
1213 | { |
1214 | return Standard_False; |
1215 | } |
1216 | break; |
a6eb515f |
1217 | } |
0499eb06 |
1218 | case TopAbs_EDGE: |
a6eb515f |
1219 | { |
0499eb06 |
1220 | TopoDS_Edge anEdge = TopoDS::Edge (theShape); |
787ff240 |
1221 | if (!PrsDim_Dimension::CircleFromEdge (anEdge, theCircle, aFirstPoint, aLastPoint)) |
0499eb06 |
1222 | { |
1223 | return Standard_False; |
1224 | } |
1225 | break; |
a6eb515f |
1226 | } |
0499eb06 |
1227 | case TopAbs_COMPOUND: |
1228 | case TopAbs_COMPSOLID: |
1229 | case TopAbs_SOLID: |
1230 | case TopAbs_SHELL: |
1231 | case TopAbs_VERTEX: |
1232 | case TopAbs_SHAPE: |
1233 | default: |
a6eb515f |
1234 | return Standard_False; |
a6eb515f |
1235 | } |
60bf98ae |
1236 | |
1237 | theIsClosed = aFirstPoint.IsEqual (aLastPoint, Precision::Confusion()); |
1238 | |
a6eb515f |
1239 | gp_Pnt aCenter = theCircle.Location(); |
60bf98ae |
1240 | |
1241 | if (theIsClosed) // Circle |
a6eb515f |
1242 | { |
a6eb515f |
1243 | gp_Dir anXDir = theCircle.XAxis().Direction(); |
1244 | theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius()); |
a6eb515f |
1245 | } |
60bf98ae |
1246 | else // Arc |
a6eb515f |
1247 | { |
a6eb515f |
1248 | aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint); |
1249 | aLastParam = ElCLib::Parameter (theCircle, aLastPoint); |
1250 | if (aFirstParam > aLastParam) |
1251 | { |
1252 | aFirstParam -= 2.0 * M_PI; |
1253 | } |
60bf98ae |
1254 | |
a6eb515f |
1255 | Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5; |
1256 | gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius (); |
1257 | theMiddleArcPoint = aCenter.Translated (aVec); |
a6eb515f |
1258 | } |
1259 | |
1260 | return Standard_True; |
1261 | } |
1262 | |
a6eb515f |
1263 | //======================================================================= |
1264 | //function : ComputeSelection |
1265 | //purpose : |
1266 | //======================================================================= |
787ff240 |
1267 | void PrsDim_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, |
1268 | const Standard_Integer theMode) |
a6eb515f |
1269 | { |
91b16a64 |
1270 | if (!mySelectionGeom.IsComputed) |
a6eb515f |
1271 | { |
1272 | return; |
1273 | } |
1274 | |
787ff240 |
1275 | PrsDim_DimensionSelectionMode aSelectionMode = (PrsDim_DimensionSelectionMode)theMode; |
a6eb515f |
1276 | |
fe83e1ea |
1277 | // init appropriate entity owner |
1278 | Handle(SelectMgr_EntityOwner) aSensitiveOwner; |
a6eb515f |
1279 | |
fe83e1ea |
1280 | switch (aSelectionMode) |
a6eb515f |
1281 | { |
fe83e1ea |
1282 | // neutral selection owner |
787ff240 |
1283 | case PrsDim_DimensionSelectionMode_All: |
fe83e1ea |
1284 | aSensitiveOwner = new SelectMgr_EntityOwner (this, THE_NEUTRAL_SEL_PRIORITY); |
1285 | break; |
1286 | |
1287 | // local selection owners |
787ff240 |
1288 | case PrsDim_DimensionSelectionMode_Line: |
1289 | case PrsDim_DimensionSelectionMode_Text: |
1290 | aSensitiveOwner = new PrsDim_DimensionOwner (this, aSelectionMode, THE_LOCAL_SEL_PRIORITY); |
fe83e1ea |
1291 | break; |
a6eb515f |
1292 | } |
fe83e1ea |
1293 | |
787ff240 |
1294 | if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Line) |
a6eb515f |
1295 | { |
fe83e1ea |
1296 | // sensitives for dimension line segments |
1297 | Handle(Select3D_SensitiveGroup) aGroupOfSensitives = new Select3D_SensitiveGroup (aSensitiveOwner); |
1298 | |
1299 | SelectionGeometry::SeqOfCurves::Iterator aCurveIt (mySelectionGeom.DimensionLine); |
1300 | for (; aCurveIt.More(); aCurveIt.Next()) |
1301 | { |
1302 | const SelectionGeometry::HCurve& aCurveData = aCurveIt.Value(); |
1303 | |
1304 | TColgp_Array1OfPnt aSensitivePnts (1, aCurveData->Length()); |
1305 | for (Standard_Integer aPntIt = 1; aPntIt <= aCurveData->Length(); ++aPntIt) |
1306 | { |
1307 | aSensitivePnts.ChangeValue (aPntIt) = aCurveData->Value (aPntIt); |
1308 | } |
1309 | |
1310 | aGroupOfSensitives->Add (new Select3D_SensitiveCurve (aSensitiveOwner, aSensitivePnts)); |
1311 | } |
1312 | |
ee2be2a8 |
1313 | Standard_Real anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length(); |
1314 | Standard_Real anArrowAngle = myDrawer->DimensionAspect()->ArrowAspect()->Angle(); |
fe83e1ea |
1315 | |
1316 | // sensitives for arrows |
1317 | SelectionGeometry::SeqOfArrows::Iterator anArrowIt (mySelectionGeom.Arrows); |
1318 | for (; anArrowIt.More(); anArrowIt.Next()) |
1319 | { |
1320 | const SelectionGeometry::HArrow& anArrow = anArrowIt.Value(); |
1321 | |
1322 | gp_Pnt aSidePnt1 (gp::Origin()); |
1323 | gp_Pnt aSidePnt2 (gp::Origin()); |
60bf98ae |
1324 | const gp_Dir& aPlane = GetPlane().Axis().Direction(); |
fe83e1ea |
1325 | const gp_Pnt& aPeak = anArrow->Position; |
1326 | const gp_Dir& aDir = anArrow->Direction; |
1327 | |
1328 | // compute points for arrow in plane |
1329 | PointsForArrow (aPeak, aDir, aPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2); |
1330 | |
1331 | aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2)); |
1332 | |
1333 | if (!myDrawer->DimensionAspect()->IsArrows3d()) |
1334 | { |
1335 | continue; |
1336 | } |
1337 | |
1338 | // compute points for orthogonal sensitive plane |
1339 | gp_Dir anOrthoPlane = anArrow->Direction.Crossed (aPlane); |
1340 | |
1341 | PointsForArrow (aPeak, aDir, anOrthoPlane, anArrowLength, anArrowAngle, aSidePnt1, aSidePnt2); |
1342 | |
1343 | aGroupOfSensitives->Add (new Select3D_SensitiveTriangle (aSensitiveOwner, aPeak, aSidePnt1, aSidePnt2)); |
1344 | } |
1345 | |
1346 | theSelection->Add (aGroupOfSensitives); |
a6eb515f |
1347 | } |
fe83e1ea |
1348 | |
1349 | // sensitives for text element |
787ff240 |
1350 | if (aSelectionMode == PrsDim_DimensionSelectionMode_All || aSelectionMode == PrsDim_DimensionSelectionMode_Text) |
a6eb515f |
1351 | { |
fe83e1ea |
1352 | Handle(Select3D_SensitiveEntity) aTextSensitive; |
1353 | |
1354 | gp_Ax2 aTextAxes (mySelectionGeom.TextPos, |
60bf98ae |
1355 | GetPlane().Axis().Direction(), |
fe83e1ea |
1356 | mySelectionGeom.TextDir); |
1357 | |
1358 | if (myDrawer->DimensionAspect()->IsText3d()) |
1359 | { |
1360 | // sensitive planar rectangle for text |
1361 | Standard_Real aDx = mySelectionGeom.TextWidth * 0.5; |
1362 | Standard_Real aDy = mySelectionGeom.TextHeight * 0.5; |
1363 | |
1364 | gp_Trsf aLabelPlane; |
1365 | aLabelPlane.SetTransformation (aTextAxes, gp::XOY()); |
1366 | |
51f8f60c |
1367 | TColgp_Array1OfPnt aRectanglePoints(1, 4); |
1368 | aRectanglePoints.ChangeValue(1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane); |
1369 | aRectanglePoints.ChangeValue(2) = gp_Pnt (-aDx, aDy, 0.0).Transformed (aLabelPlane); |
1370 | aRectanglePoints.ChangeValue(3) = gp_Pnt ( aDx, aDy, 0.0).Transformed (aLabelPlane); |
1371 | aRectanglePoints.ChangeValue(4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane); |
fe83e1ea |
1372 | |
51f8f60c |
1373 | Poly_Array1OfTriangle aTriangles(1, 2); |
1374 | aTriangles.ChangeValue(1) = Poly_Triangle(1, 2, 3); |
1375 | aTriangles.ChangeValue(2) = Poly_Triangle(1, 3, 4); |
1376 | |
1377 | Handle(Poly_Triangulation) aRectanglePoly = |
1378 | new Poly_Triangulation(aRectanglePoints, aTriangles); |
1379 | |
1380 | aTextSensitive = |
1381 | new Select3D_SensitiveTriangulation (aSensitiveOwner, aRectanglePoly, TopLoc_Location(), Standard_True); |
fe83e1ea |
1382 | } |
1383 | else |
1384 | { |
1385 | gp_Circ aTextGeom (aTextAxes, mySelToleranceForText2d != 0.0 |
1386 | ? mySelToleranceForText2d : 1.0); |
7f24b768 |
1387 | aTextSensitive = new Select3D_SensitiveCircle (aSensitiveOwner, aTextGeom, Standard_True); |
fe83e1ea |
1388 | } |
1389 | |
1390 | theSelection->Add (aTextSensitive); |
a6eb515f |
1391 | } |
fe83e1ea |
1392 | |
1393 | // callback for flyout sensitive calculation |
787ff240 |
1394 | if (aSelectionMode == PrsDim_DimensionSelectionMode_All) |
d7bffd44 |
1395 | { |
60bf98ae |
1396 | ComputeFlyoutSelection (theSelection, aSensitiveOwner); |
d7bffd44 |
1397 | } |
fe83e1ea |
1398 | } |
1399 | |
1400 | //======================================================================= |
1401 | //function : PointsForArrow |
1402 | //purpose : |
1403 | //======================================================================= |
787ff240 |
1404 | void PrsDim_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt, |
1405 | const gp_Dir& theDirection, |
1406 | const gp_Dir& thePlane, |
1407 | const Standard_Real theArrowLength, |
1408 | const Standard_Real theArrowAngle, |
1409 | gp_Pnt& theSidePnt1, |
1410 | gp_Pnt& theSidePnt2) |
fe83e1ea |
1411 | { |
1412 | gp_Lin anArrowLin (thePeakPnt, theDirection.Reversed()); |
1413 | gp_Pnt anArrowEnd = ElCLib::Value (theArrowLength, anArrowLin); |
1414 | gp_Lin anEdgeLin (anArrowEnd, theDirection.Crossed (thePlane)); |
1415 | |
1416 | Standard_Real anEdgeLength = Tan (theArrowAngle) * theArrowLength; |
a6eb515f |
1417 | |
fe83e1ea |
1418 | theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin); |
1419 | theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin); |
a6eb515f |
1420 | } |
af203d54 |
1421 | |
1422 | //======================================================================= |
1423 | //function : GetTextPositionForLinear |
1424 | //purpose : |
1425 | //======================================================================= |
787ff240 |
1426 | gp_Pnt PrsDim_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint, |
1427 | const gp_Pnt& theSecondPoint, |
1428 | const Standard_Boolean theIsOneSide) const |
af203d54 |
1429 | { |
91b16a64 |
1430 | if (!IsValid()) |
af203d54 |
1431 | { |
1432 | return gp::Origin(); |
1433 | } |
1434 | |
1435 | gp_Pnt aTextPosition (gp::Origin()); |
1436 | |
1437 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
1438 | |
1439 | // Get label alignment and arrow orientation. |
1440 | Standard_Integer aLabelPosition = 0; |
1441 | Standard_Boolean isArrowsExternal = Standard_False; |
1442 | FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, |
1443 | aDimensionAspect->TextHorizontalPosition(), |
1444 | aLabelPosition, isArrowsExternal); |
1445 | |
1446 | // Compute dimension line points. |
1447 | gp_Dir aPlaneNormal = GetPlane().Axis().Direction(); |
1448 | gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint); |
1449 | |
1450 | // Compute flyout direction vector |
1451 | gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec); |
1452 | |
1453 | // create lines for layouts |
1454 | gp_Lin aLine1 (theFirstPoint, aFlyoutVector); |
1455 | gp_Lin aLine2 (theSecondPoint, aFlyoutVector); |
1456 | // Get flyout end points |
1457 | gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); |
1458 | gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); |
1459 | |
1460 | // Get text position. |
1461 | switch (aLabelPosition & LabelPosition_HMask) |
1462 | { |
1463 | case LabelPosition_Left: |
1464 | { |
1465 | gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint); |
1466 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
1467 | |
1468 | Standard_Real anOffset = isArrowsExternal |
1469 | ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() |
1470 | : anExtensionSize; |
1471 | gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset; |
1472 | aTextPosition = aLineEndPoint.Translated (anExtensionVec); |
1473 | } |
1474 | break; |
1475 | case LabelPosition_Right: |
1476 | { |
1477 | gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint); |
1478 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
1479 | |
1480 | Standard_Real anOffset = isArrowsExternal |
1481 | ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() |
1482 | : anExtensionSize; |
1483 | gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset; |
1484 | aTextPosition = aLineBegPoint.Translated (anExtensionVec); |
1485 | } |
1486 | break; |
1487 | case LabelPosition_HCenter: |
1488 | { |
1489 | aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5; |
1490 | } |
1491 | break; |
1492 | } |
1493 | |
1494 | return aTextPosition; |
1495 | } |
1496 | |
1497 | //======================================================================= |
91b16a64 |
1498 | //function : AdjustParametersForLinear |
af203d54 |
1499 | //purpose : |
1500 | //======================================================================= |
787ff240 |
1501 | Standard_Boolean PrsDim_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos, |
1502 | const gp_Pnt& theFirstPoint, |
1503 | const gp_Pnt& theSecondPoint, |
1504 | Standard_Real& theExtensionSize, |
1505 | Prs3d_DimensionTextHorizontalPosition& theAlignment, |
1506 | Standard_Real& theFlyout, |
1507 | gp_Pln& thePlane, |
1508 | Standard_Boolean& theIsPlaneOld) const |
af203d54 |
1509 | { |
1510 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
1511 | Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
1512 | |
af203d54 |
1513 | gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint); |
1514 | gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint); |
1515 | |
91b16a64 |
1516 | // Don't set new plane if the text position lies on the attachment points line. |
1517 | gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir); |
1518 | if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion())) |
1519 | { |
1520 | //Set new automatic plane. |
1521 | thePlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint); |
1522 | theIsPlaneOld = Standard_False; |
1523 | } |
1524 | |
af203d54 |
1525 | // Compute flyout direction vector. |
91b16a64 |
1526 | gp_Dir aPlaneNormal = GetPlane().Axis().Direction(); |
af203d54 |
1527 | gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir; |
1528 | |
91b16a64 |
1529 | // Additional check of collinearity of the plane normal and attachment points vector. |
1530 | if (aPlaneNormal.IsParallel (aTargetPointsDir, Precision::Angular())) |
1531 | { |
1532 | return Standard_False; |
1533 | } |
1534 | |
af203d54 |
1535 | // Set flyout. |
1536 | gp_Vec aFirstToTextVec (theFirstPoint, theTextPos); |
1537 | |
1538 | Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir); |
1539 | |
1540 | gp_Pnt aTextPosProj = theFirstPoint.Translated |
1541 | (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos); |
1542 | |
1543 | // Compute flyout value and direction. |
1544 | gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos); |
1545 | |
91b16a64 |
1546 | theFlyout = 0.0; |
1547 | if (aFlyoutVector.Magnitude() > Precision::Confusion()) |
1548 | { |
1549 | theFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular()) |
1550 | ? -aFlyoutVector.Magnitude() |
1551 | : aFlyoutVector.Magnitude(); |
1552 | } |
1553 | |
af203d54 |
1554 | // Compute attach points (through which main dimension line passes). |
1555 | gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector); |
1556 | gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector); |
1557 | |
91b16a64 |
1558 | // Set horizontal text alignment. |
af203d54 |
1559 | if (aCos < 0.0) |
1560 | { |
1561 | theAlignment = Prs3d_DTHP_Left; |
1562 | |
1563 | Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength; |
1564 | theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize; |
1565 | } |
1566 | else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint)) |
1567 | { |
1568 | theAlignment = Prs3d_DTHP_Right; |
1569 | |
1570 | Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength; |
1571 | theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize; |
1572 | } |
1573 | else |
1574 | { |
1575 | theAlignment = Prs3d_DTHP_Center; |
1576 | } |
91b16a64 |
1577 | return Standard_True; |
af203d54 |
1578 | } |
1579 | |
1580 | //======================================================================= |
1581 | //function : FitTextAlignmentForLinear |
1582 | //purpose : |
1583 | //======================================================================= |
787ff240 |
1584 | void PrsDim_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint, |
1585 | const gp_Pnt& theSecondPoint, |
1586 | const Standard_Boolean theIsOneSide, |
1587 | const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, |
1588 | Standard_Integer& theLabelPosition, |
1589 | Standard_Boolean& theIsArrowsExternal) const |
af203d54 |
1590 | { |
1591 | theLabelPosition = LabelPosition_None; |
1592 | theIsArrowsExternal = Standard_False; |
1593 | |
1594 | // Compute dimension line points |
1595 | gp_Ax1 aPlaneNormal = GetPlane().Axis(); |
1596 | gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint); |
1597 | |
1598 | // compute flyout direction vector |
1599 | gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector; |
1600 | |
1601 | // create lines for layouts |
1602 | gp_Lin aLine1 (theFirstPoint, aFlyoutVector); |
1603 | gp_Lin aLine2 (theSecondPoint, aFlyoutVector); |
1604 | |
1605 | // Get flyout end points |
1606 | gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); |
1607 | gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); |
1608 | |
1609 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
1610 | |
af203d54 |
1611 | // For extensions we need to know arrow size, text size and extension size: get it from aspect |
ee2be2a8 |
1612 | Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
af203d54 |
1613 | |
1614 | // prepare label string and compute its geometrical width |
1615 | Standard_Real aLabelWidth; |
1616 | TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); |
1617 | |
1618 | // Add margins to cut dimension lines for 3d text |
1619 | if (aDimensionAspect->IsText3d()) |
1620 | { |
1621 | aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; |
1622 | } |
1623 | |
1624 | // Handle user-defined and automatic arrow placement |
1625 | switch (aDimensionAspect->ArrowOrientation()) |
1626 | { |
1627 | case Prs3d_DAO_External: theIsArrowsExternal = true; break; |
1628 | case Prs3d_DAO_Internal: theIsArrowsExternal = false; break; |
1629 | case Prs3d_DAO_Fit: |
1630 | { |
1631 | // Add margin to ensure a small tail between text and arrow |
1632 | Standard_Real anArrowMargin = aDimensionAspect->IsText3d() |
1633 | ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN |
1634 | : 0.0; |
1635 | |
1636 | Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); |
1637 | Standard_Real anArrowsWidth = theIsOneSide |
1638 | ? anArrowLength + anArrowMargin |
1639 | : (anArrowLength + anArrowMargin) * 2.0; |
1640 | |
1641 | theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth; |
1642 | break; |
1643 | } |
1644 | } |
1645 | |
1646 | // Handle user-defined and automatic text placement |
1647 | switch (theHorizontalTextPos) |
1648 | { |
1649 | case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break; |
1650 | case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break; |
1651 | case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break; |
1652 | case Prs3d_DTHP_Fit: |
1653 | { |
1654 | Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); |
1655 | Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength; |
1656 | Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth; |
1657 | |
1658 | theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; |
1659 | break; |
1660 | } |
1661 | } |
1662 | |
1663 | // Handle vertical text placement options |
1664 | switch (aDimensionAspect->TextVerticalPosition()) |
1665 | { |
1666 | case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break; |
1667 | case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break; |
1668 | case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break; |
1669 | } |
1670 | } |
1671 | |
1672 | //======================================================================= |
1673 | //function : UnsetFixedTextPosition |
1674 | //purpose : |
1675 | //======================================================================= |
787ff240 |
1676 | void PrsDim_Dimension::UnsetFixedTextPosition() |
af203d54 |
1677 | { |
1678 | myIsTextPositionFixed = Standard_False; |
1679 | myFixedTextPosition = gp::Origin(); |
1680 | } |