a6eb515f |
1 | // Copyright (c) 1999-2013 OPEN CASCADE SAS |
2 | // |
3 | // The content of this file is subject to the Open CASCADE Technology Public |
4 | // License Version 6.5 (the "License"). You may not use the content of this file |
5 | // except in compliance with the License. Please obtain a copy of the License |
6 | // at http://www.opencascade.org and read it completely before using this file. |
7 | // |
8 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
9 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
10 | // |
11 | // The Original Code and all software distributed under the License is |
12 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
13 | // Initial Developer hereby disclaims all such warranties, including without |
14 | // limitation, any warranties of merchantability, fitness for a particular |
15 | // purpose or non-infringement. Please see the License for the specific terms |
16 | // and conditions governing the rights and limitations under the License. |
17 | |
a6eb515f |
18 | #include <AIS_Dimension.hxx> |
d7bffd44 |
19 | |
20 | #include <AIS.hxx> |
a6eb515f |
21 | #include <AIS_DimensionDisplayMode.hxx> |
22 | #include <AIS_DimensionOwner.hxx> |
23 | #include <AIS_Drawer.hxx> |
24 | #include <Adaptor3d_HCurve.hxx> |
25 | #include <BRepAdaptor_Curve.hxx> |
26 | #include <BRepAdaptor_Surface.hxx> |
27 | #include <BRepBuilderAPI_MakeEdge.hxx> |
28 | #include <BRepLib_MakeVertex.hxx> |
29 | #include <BRepBndLib.hxx> |
30 | #include <GeomAdaptor_Curve.hxx> |
31 | #include <ElCLib.hxx> |
32 | #include <Font_BRepFont.hxx> |
33 | #include <GC_MakeCircle.hxx> |
34 | #include <Geom_Circle.hxx> |
35 | #include <Geom_Plane.hxx> |
36 | #include <Geom_TrimmedCurve.hxx> |
37 | #include <gce_MakeDir.hxx> |
38 | #include <gce_MakeLin.hxx> |
39 | #include <Graphic3d_ArrayOfSegments.hxx> |
40 | #include <Graphic3d_ArrayOfTriangles.hxx> |
41 | #include <Graphic3d_AspectLine3d.hxx> |
42 | #include <Graphic3d_AspectFillArea3d.hxx> |
43 | #include <Graphic3d_AspectText3d.hxx> |
44 | #include <Graphic3d_Group.hxx> |
45 | #include <PrsMgr_PresentationManager3d.hxx> |
46 | #include <Prs3d_Arrow.hxx> |
47 | #include <Prs3d_ArrowAspect.hxx> |
48 | #include <Prs3d_Drawer.hxx> |
49 | #include <Prs3d_LineAspect.hxx> |
50 | #include <Prs3d_Presentation.hxx> |
51 | #include <Prs3d_Root.hxx> |
52 | #include <Prs3d_ShadingAspect.hxx> |
53 | #include <Prs3d_Text.hxx> |
54 | #include <SelectMgr_EntityOwner.hxx> |
55 | #include <SelectMgr_Selection.hxx> |
56 | #include <SelectMgr_SequenceOfOwner.hxx> |
57 | #include <Select3D_ListIteratorOfListOfSensitive.hxx> |
58 | #include <Select3D_ListOfSensitive.hxx> |
59 | #include <Select3D_SensitiveBox.hxx> |
60 | #include <Select3D_SensitiveCircle.hxx> |
61 | #include <Select3D_SensitiveGroup.hxx> |
62 | #include <Select3D_SensitiveSegment.hxx> |
63 | #include <Standard_CString.hxx> |
64 | #include <StdPrs_ShadedShape.hxx> |
65 | #include <StdPrs_WFShape.hxx> |
66 | #include <TCollection_AsciiString.hxx> |
67 | #include <TCollection_ExtendedString.hxx> |
68 | #include <TopExp_Explorer.hxx> |
69 | #include <TopoDS.hxx> |
70 | #include <TopoDS_Vertex.hxx> |
71 | #include <Units.hxx> |
72 | #include <Units_UnitsDictionary.hxx> |
73 | #include <UnitsAPI.hxx> |
74 | #include <UnitsAPI_SystemUnits.hxx> |
75 | |
76 | IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject) |
77 | IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject) |
78 | |
d7bffd44 |
79 | namespace |
a6eb515f |
80 | { |
d7bffd44 |
81 | static const Standard_Utf32Char THE_FILL_CHARACTER ('0'); |
82 | static const TCollection_ExtendedString THE_EMPTY_LABEL; |
83 | static const Standard_Real THE_3D_TEXT_MARGIN = 0.1; |
84 | }; |
a6eb515f |
85 | |
86 | //======================================================================= |
87 | //function : Constructor |
88 | //purpose : |
89 | //======================================================================= |
d7bffd44 |
90 | AIS_Dimension::AIS_Dimension() |
a6eb515f |
91 | : AIS_InteractiveObject(), |
92 | myDefaultPlane (gp_Pln (gp::XOY())), |
93 | myIsWorkingPlaneCustom (Standard_False), |
94 | myValue (0.0), |
95 | myIsValueCustom (Standard_False), |
96 | myUnitsQuantity (TCollection_AsciiString("LENGTH")), |
97 | myToDisplayUnits (Standard_False), |
98 | mySpecialSymbol (' '), |
99 | myDisplaySpecialSymbol (AIS_DSS_No), |
100 | myIsTextReversed (Standard_False), |
a6eb515f |
101 | myIsInitialized (Standard_False), |
62b6361a |
102 | myFlyout (0.0), |
d7bffd44 |
103 | myKindOfDimension (AIS_KOD_NONE) |
a6eb515f |
104 | { |
105 | ResetWorkingPlane(); |
106 | // Units default settings |
107 | UnitsAPI::SetLocalSystem (UnitsAPI_SI); |
108 | myModelUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString()); |
109 | myDisplayUnits = Units::DictionaryOfUnits()->ActiveUnit (myUnitsQuantity.ToCString()); |
a6eb515f |
110 | } |
111 | |
112 | //======================================================================= |
113 | //function : AcceptDisplayMode |
114 | //purpose : Checks if display mode <theMode> is allowed to display object. |
115 | //======================================================================= |
a6eb515f |
116 | Standard_Boolean AIS_Dimension::AcceptDisplayMode (const Standard_Integer theMode) const |
117 | { |
118 | return theMode == 0 ? Standard_True : Standard_False; |
119 | } |
120 | |
121 | //======================================================================= |
122 | //function : computeValue |
123 | //purpose : Computes dimension value in display units. |
124 | //======================================================================= |
a6eb515f |
125 | void AIS_Dimension::computeValue() |
126 | { |
127 | UnitsAPI::SetCurrentUnit (myUnitsQuantity.ToCString(), myModelUnits.ToCString()); |
128 | myValue = UnitsAPI::CurrentFromLS (myValue, myUnitsQuantity.ToCString()); |
129 | myValue = valueToDisplayUnits(); |
130 | } |
131 | |
132 | //======================================================================= |
133 | //function : countDefaultPlane |
134 | //purpose : |
135 | //======================================================================= |
a6eb515f |
136 | void AIS_Dimension::countDefaultPlane() |
137 | { |
138 | } |
139 | |
140 | //======================================================================= |
141 | //function : GetWorkingPlane |
142 | //purpose : |
143 | //======================================================================= |
a6eb515f |
144 | const gp_Pln& AIS_Dimension::GetWorkingPlane() const |
145 | { |
146 | return myWorkingPlane; |
147 | } |
148 | |
149 | //======================================================================= |
150 | //function : SetWorkingPlane |
151 | //purpose : |
152 | //======================================================================= |
a6eb515f |
153 | void AIS_Dimension::SetWorkingPlane (const gp_Pln& thePlane) |
154 | { |
155 | myWorkingPlane = thePlane; |
156 | myIsWorkingPlaneCustom = Standard_True; |
157 | } |
158 | |
159 | //======================================================================= |
160 | //function : ResetWorkingPlane |
161 | //purpose : Set default value of working plane |
162 | //======================================================================= |
a6eb515f |
163 | void AIS_Dimension::ResetWorkingPlane() |
164 | { |
165 | myWorkingPlane = myDefaultPlane; |
166 | myIsWorkingPlaneCustom = Standard_False; |
167 | } |
168 | |
169 | //======================================================================= |
170 | //function : resetWorkingPlane |
171 | //purpose : Set default value of working plane |
172 | // Only for internal use. |
173 | //======================================================================= |
a6eb515f |
174 | void AIS_Dimension::resetWorkingPlane (const gp_Pln& theNewDefaultPlane) |
175 | { |
176 | myDefaultPlane = theNewDefaultPlane; |
177 | ResetWorkingPlane(); |
178 | } |
179 | |
180 | //======================================================================= |
181 | //function : valueInDisplayUnits |
182 | //purpose : |
183 | //======================================================================= |
a6eb515f |
184 | Standard_Real AIS_Dimension::valueToDisplayUnits() |
185 | { |
186 | return UnitsAPI::AnyToAny (myValue, |
187 | myModelUnits.ToCString(), |
188 | myDisplayUnits.ToCString()); |
189 | } |
190 | |
191 | //======================================================================= |
192 | //function : KindOfDimension |
193 | //purpose : |
194 | //======================================================================= |
a6eb515f |
195 | AIS_KindOfDimension AIS_Dimension::KindOfDimension() const |
196 | { |
197 | return myKindOfDimension; |
198 | } |
199 | |
200 | //======================================================================= |
201 | //function : SetKindOfDimension |
202 | //purpose : |
203 | //======================================================================= |
a6eb515f |
204 | void AIS_Dimension::SetKindOfDimension (const AIS_KindOfDimension theKindOfDimension) |
205 | { |
206 | myKindOfDimension = theKindOfDimension; |
207 | } |
208 | |
a6eb515f |
209 | //======================================================================= |
210 | //function : GetValue |
211 | //purpose : |
212 | //======================================================================= |
a6eb515f |
213 | Standard_Real AIS_Dimension::GetValue() const |
214 | { |
215 | return myValue; |
216 | } |
217 | |
218 | //======================================================================= |
219 | //function : SetCustomValue |
220 | //purpose : |
221 | //======================================================================= |
a6eb515f |
222 | void AIS_Dimension::SetCustomValue (const Standard_Real theValue) |
223 | { |
224 | myValue = theValue; |
225 | myIsValueCustom = Standard_True; |
226 | } |
227 | |
228 | //======================================================================= |
229 | //function : SetFirstShape |
230 | //purpose : |
231 | //======================================================================= |
a6eb515f |
232 | void AIS_Dimension::SetFirstShape (const TopoDS_Shape& theShape) |
233 | { |
234 | myFirstShape = theShape; |
235 | myIsInitialized = Standard_False; |
236 | resetGeom(); |
237 | } |
238 | |
239 | //======================================================================= |
240 | //function : SetSecondShape |
241 | //purpose : |
242 | //======================================================================= |
a6eb515f |
243 | void AIS_Dimension::SetSecondShape (const TopoDS_Shape& theShape) |
244 | { |
245 | mySecondShape = theShape; |
246 | myIsInitialized = Standard_False; |
247 | resetGeom(); |
248 | } |
249 | |
250 | //======================================================================= |
251 | //function : getTextWidthAndString |
252 | //purpose : |
253 | //======================================================================= |
a6eb515f |
254 | void AIS_Dimension::getTextWidthAndString (Quantity_Length& theWidth, |
255 | TCollection_ExtendedString& theString) const |
256 | { |
257 | char aValueSimpleStr[25]; |
258 | sprintf (aValueSimpleStr, "%g", GetValue()); |
259 | theString = TCollection_ExtendedString (aValueSimpleStr); |
260 | |
261 | if (IsUnitsDisplayed()) |
262 | { |
263 | theString += " "; |
264 | theString += TCollection_ExtendedString (myDisplayUnits); |
265 | } |
266 | |
267 | if (myDisplaySpecialSymbol == AIS_DSS_Before) |
268 | { |
269 | theString = TCollection_ExtendedString (mySpecialSymbol) + theString; |
270 | } |
271 | else if (myDisplaySpecialSymbol == AIS_DSS_After) |
272 | { |
273 | theString += TCollection_ExtendedString (mySpecialSymbol); |
274 | } |
275 | |
d7bffd44 |
276 | // Get text style parameters |
a6eb515f |
277 | Quantity_Color aColor; |
d7bffd44 |
278 | Standard_CString aFontName; |
a6eb515f |
279 | Standard_Real aFactor; |
280 | Standard_Real aSpace; |
d7bffd44 |
281 | myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace); |
282 | // Init font instance |
283 | Handle(Font_FTFont) aFont = new Font_FTFont (); |
284 | aFont->Init (aFontName, |
285 | myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect(), |
286 | (Standard_Integer) myDrawer->DimensionAspect()->TextAspect()->Height(), 72); |
287 | |
288 | TCollection_ExtendedString aString (theString); |
289 | aString += "."; |
290 | Standard_PCharacter aUtf8String = new Standard_Character[aString.Length()]; |
291 | Standard_Integer aStrLength = aString.ToUTF8CString(aUtf8String); |
292 | theWidth = 0.0; |
293 | for (Standard_Integer anIt = 0; anIt < aStrLength - 1; ++anIt) |
294 | { |
295 | Standard_Real anAdvance = aFont->AdvanceX (aUtf8String[anIt], aUtf8String[anIt + 1]); |
296 | theWidth += anAdvance; |
297 | } |
a6eb515f |
298 | } |
299 | |
300 | //======================================================================= |
301 | //function : drawArrow |
302 | //purpose : |
303 | //======================================================================= |
a6eb515f |
304 | void AIS_Dimension::drawArrow (const Handle(Prs3d_Presentation)& thePresentation, |
305 | const gp_Pnt& theLocation, |
306 | const gp_Dir& theDirection) |
307 | { |
308 | Prs3d_Root::NewGroup (thePresentation); |
309 | Quantity_Length anArrowLength = myDrawer->DimensionAspect()->ArrowAspect()->Length(); |
310 | |
311 | if (myDrawer->DimensionAspect()->IsArrows3d()) |
312 | { |
313 | Prs3d_Arrow::Draw (thePresentation, |
314 | theLocation, |
d7bffd44 |
315 | theDirection, |
a6eb515f |
316 | myDrawer->DimensionAspect()->ArrowAspect()->Angle(), |
317 | anArrowLength); |
318 | } |
319 | else |
320 | { |
d7bffd44 |
321 | gp_Vec aBackDir (theDirection.Reversed()); |
a6eb515f |
322 | Quantity_Length theCathetusLength = anArrowLength / Cos (M_PI / 9.0); |
323 | Handle(Graphic3d_ArrayOfTriangles) anArrow = new Graphic3d_ArrayOfTriangles(3); |
d7bffd44 |
324 | gp_Pnt aLeftPoint (theLocation.Translated (aBackDir.Rotated (myWorkingPlane.Axis(), M_PI / 9.0) * theCathetusLength)); |
325 | gp_Pnt aRightPoint (theLocation.Translated (aBackDir.Rotated (myWorkingPlane.Axis(), M_PI * 17.0 / 9.0) * theCathetusLength)); |
a6eb515f |
326 | |
327 | anArrow->AddVertex (aLeftPoint); |
328 | anArrow->AddVertex (theLocation); |
329 | anArrow->AddVertex (aRightPoint); |
330 | |
331 | // Set aspect for arrow triangles |
332 | Quantity_Color aColor; |
333 | Aspect_TypeOfLine aTOL; |
334 | Standard_Real aWidth; |
335 | myDrawer->DimensionAspect()->ArrowAspect()->Aspect()->Values (aColor, aTOL, aWidth); |
336 | Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT); |
337 | aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT); |
338 | aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE); |
339 | aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR); |
d7bffd44 |
340 | |
341 | Handle(Prs3d_ShadingAspect) aShadingStyle = new Prs3d_ShadingAspect(); |
342 | aShadingStyle->SetColor (aColor); |
343 | aShadingStyle->SetMaterial (aShadeMat); |
344 | |
345 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aShadingStyle->Aspect()); |
346 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anArrow); |
a6eb515f |
347 | } |
348 | } |
349 | |
350 | //======================================================================= |
351 | //function : drawText |
352 | //purpose : |
353 | //======================================================================= |
a6eb515f |
354 | Standard_Real AIS_Dimension::drawText (const Handle(Prs3d_Presentation)& thePresentation, |
355 | const gp_Dir& theTextDir, |
356 | const TCollection_ExtendedString theText, |
d7bffd44 |
357 | const AIS_DimensionDisplayMode theMode, |
358 | const Standard_Integer theLabelPosition) |
a6eb515f |
359 | { |
360 | Standard_Real aTextWidth (0.0), aTextHeight (0.0); |
361 | if (theMode == AIS_DDM_Line) |
d7bffd44 |
362 | { |
363 | return 0.0; |
364 | } |
a6eb515f |
365 | |
366 | if (myDrawer->DimensionAspect()->IsText3d()) |
367 | { |
368 | // Getting font parameters |
369 | Quantity_Color aColor; |
370 | Standard_CString aFontName; |
371 | Standard_Real anExpansionFactor; |
372 | Standard_Real aSpace; |
373 | myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace); |
374 | Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect(); |
375 | Standard_Real aHeight = myDrawer->DimensionAspect()->TextAspect()->Height(); |
376 | |
377 | // Creating TopoDS_Shape for text |
378 | Font_BRepFont aFont (aFontName, aFontAspect, aHeight); |
379 | NCollection_String aText = (Standard_Utf16Char* )theText.ToExtString(); |
380 | TopoDS_Shape aTextShape = aFont.RenderText (aText); |
381 | |
382 | // Formating text position in XOY plane |
383 | Bnd_Box aTextBndBox; |
384 | BRepBndLib::AddClose (aTextShape, aTextBndBox); |
385 | Standard_Real aXMin, anYMin, aZMin, aXMax, anYMax, aZMax; |
386 | aTextBndBox.Get (aXMin, anYMin, aZMin, aXMax, anYMax, aZMax); |
387 | aTextWidth = aXMax - aXMin; |
388 | aTextHeight = anYMax - anYMin; |
d7bffd44 |
389 | |
390 | Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask; |
391 | Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask; |
392 | |
393 | gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir); |
394 | |
395 | // compute label offsets |
396 | Standard_Real aMarginSize = aHeight * THE_3D_TEXT_MARGIN; |
397 | Standard_Real aCenterHOffset = 0.0; |
398 | Standard_Real aCenterVOffset = 0.0; |
399 | switch (aHLabelPos) |
a6eb515f |
400 | { |
d7bffd44 |
401 | case LabelPosition_HCenter : aCenterHOffset = 0.0; break; |
402 | case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break; |
403 | case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break; |
a6eb515f |
404 | } |
d7bffd44 |
405 | switch (aVLabelPos) |
a6eb515f |
406 | { |
d7bffd44 |
407 | case LabelPosition_VCenter : aCenterVOffset = 0.0; break; |
408 | case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break; |
409 | case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break; |
a6eb515f |
410 | } |
d7bffd44 |
411 | |
412 | // compute shape offset transformation |
413 | Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0; |
414 | Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0; |
415 | |
416 | gp_Trsf anOffsetTrsf; |
417 | anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0)); |
418 | aTextShape.Move (anOffsetTrsf); |
a6eb515f |
419 | |
420 | // Transform text to myWorkingPlane coordinate system |
d7bffd44 |
421 | gp_Ax3 aTextCoordSystem (myGeom.myTextPosition, myWorkingPlane.Axis().Direction(), aTextDir); |
422 | gp_Trsf aTextPlaneTrsf; |
423 | aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY())); |
424 | aTextShape.Move (aTextPlaneTrsf); |
a6eb515f |
425 | |
426 | // Set display parameters for advanced selection |
427 | BRepBndLib::AddClose (aTextShape, myGeom.myTextBndBox); |
d7bffd44 |
428 | |
429 | // Set text flipping anchors |
430 | gp_Trsf aCenterOffsetTrsf; |
431 | gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0); |
432 | aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset); |
433 | |
434 | gp_Pnt aCenterOfFlip (gp::Origin()); |
435 | aCenterOfFlip.Transform (aCenterOffsetTrsf); |
436 | aCenterOfFlip.Transform (aTextPlaneTrsf); |
437 | |
438 | gp_Ax2 aFlippingAxes (aCenterOfFlip, myWorkingPlane.Axis().Direction(), aTextDir); |
439 | Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes); |
440 | |
441 | // Draw text |
a6eb515f |
442 | if (myDrawer->DimensionAspect()->IsTextShaded()) |
443 | { |
444 | // Setting text shading and color parameters |
445 | Graphic3d_MaterialAspect aShadeMat (Graphic3d_NOM_DEFAULT); |
446 | aShadeMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT); |
447 | aShadeMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE); |
448 | aShadeMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR); |
449 | myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor); |
450 | myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor); |
451 | myDrawer->ShadingAspect()->SetMaterial (aShadeMat); |
452 | |
453 | // Drawing text |
454 | StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer); |
455 | } |
456 | else |
457 | { |
458 | // Setting color for text |
459 | myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor); |
460 | // Drawing text |
461 | StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer); |
462 | } |
d7bffd44 |
463 | Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2()); |
464 | |
465 | return aTextWidth + aMarginSize * 2.0; |
a6eb515f |
466 | } |
467 | |
d7bffd44 |
468 | myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION); |
469 | |
470 | Prs3d_Text::Draw (thePresentation, |
471 | myDrawer->DimensionAspect()->TextAspect(), |
472 | theText, |
473 | myGeom.myTextPosition); |
474 | |
475 | // For 2d text we don not create new group for lines and draw them in the same group with text |
476 | // for the proper handling of stencil test buffer. |
477 | return 0.0; |
a6eb515f |
478 | } |
479 | |
d7bffd44 |
480 | //======================================================================= |
481 | //function : drawExtension |
a6eb515f |
482 | //purpose : |
483 | //======================================================================= |
d7bffd44 |
484 | void AIS_Dimension::drawExtension (const Handle(Prs3d_Presentation)& thePresentation, |
485 | const Standard_Real theExtensionSize, |
486 | const gp_Pnt& theExtensionStart, |
487 | const gp_Dir& theExtensionDir, |
488 | const TCollection_ExtendedString& theValueString, |
489 | const AIS_DimensionDisplayMode theMode, |
490 | const Standard_Integer theLabelPosition) |
a6eb515f |
491 | { |
d7bffd44 |
492 | Standard_Real aTextWidth = 0.0; |
a6eb515f |
493 | |
d7bffd44 |
494 | Standard_Boolean isLabel = theValueString.Length() > 0; |
495 | if (isLabel) |
a6eb515f |
496 | { |
d7bffd44 |
497 | // compute text primitives; get its model width |
498 | myGeom.myTextPosition = theExtensionStart.Translated ( |
499 | gp_Vec (theExtensionDir).Scaled (theExtensionSize)); |
500 | |
501 | aTextWidth = drawText (thePresentation, |
502 | myIsTextReversed ? -theExtensionDir : theExtensionDir, |
503 | theValueString, |
504 | theMode, |
505 | theLabelPosition); |
a6eb515f |
506 | } |
507 | |
d7bffd44 |
508 | if (theMode == AIS_DDM_Text) |
a6eb515f |
509 | { |
d7bffd44 |
510 | return; |
a6eb515f |
511 | } |
512 | |
d7bffd44 |
513 | // compute graphical primitives and sensitives for extension line |
514 | gp_Pnt anExtStart = theExtensionStart; |
515 | gp_Pnt anExtEnd = !isLabel || (theLabelPosition & LabelPosition_VCenter) != 0 |
516 | ? theExtensionStart.Translated (gp_Vec (theExtensionDir) * theExtensionSize) |
517 | : theExtensionStart.Translated (gp_Vec (theExtensionDir) * (theExtensionSize + aTextWidth)); |
518 | |
519 | Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2); |
520 | anExtPrimitive->AddVertex (anExtStart); |
521 | anExtPrimitive->AddVertex (anExtEnd); |
522 | |
523 | Handle(SelectMgr_EntityOwner) aDummyOwner; |
524 | |
525 | myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (aDummyOwner, anExtStart, anExtEnd)); |
a6eb515f |
526 | |
d7bffd44 |
527 | if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All) |
a6eb515f |
528 | { |
d7bffd44 |
529 | Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True); |
530 | } |
531 | Handle(Graphic3d_AspectLine3d) aDimensionLineStyle = myDrawer->DimensionAspect()->LineAspect()->Aspect(); |
532 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionLineStyle); |
533 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (anExtPrimitive); |
534 | if (!myDrawer->DimensionAspect()->IsText3d() && theMode == AIS_DDM_All) |
535 | { |
536 | Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False); |
a6eb515f |
537 | } |
538 | } |
539 | |
540 | //======================================================================= |
541 | //function : SetDimensionAspect |
542 | //purpose : |
543 | //======================================================================= |
a6eb515f |
544 | void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect) |
545 | { |
546 | myDrawer->SetDimensionAspect (theDimensionAspect); |
547 | } |
548 | |
549 | //======================================================================= |
550 | //function : DimensionAspect |
551 | //purpose : |
552 | //======================================================================= |
a6eb515f |
553 | Handle(Prs3d_DimensionAspect) AIS_Dimension::DimensionAspect() const |
554 | { |
555 | return myDrawer->DimensionAspect(); |
556 | } |
557 | |
a6eb515f |
558 | //======================================================================= |
559 | //function : drawLinearDimension |
560 | //purpose : |
561 | //======================================================================= |
a6eb515f |
562 | void AIS_Dimension::drawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation, |
a6eb515f |
563 | const AIS_DimensionDisplayMode theMode, |
564 | const Standard_Boolean isOneSideDimension/* = Standard_False*/) |
565 | { |
566 | // Don't build any dimension for equal points |
567 | if (myFirstPoint.IsEqual (mySecondPoint, Precision::Confusion())) |
568 | { |
569 | setComputed (Standard_False); |
570 | return; |
571 | } |
d7bffd44 |
572 | |
573 | // compute dimension line points |
574 | gp_Ax1 aWorkingPlaneNormal = GetWorkingPlane().Axis(); |
575 | gp_Dir aTargetPointsVector = gce_MakeDir (myFirstPoint, mySecondPoint); |
576 | |
577 | // compute flyout direction vector |
578 | gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction() ^ aTargetPointsVector; |
579 | |
580 | // create lines for layouts |
581 | gp_Lin aLine1 (myFirstPoint, aFlyoutVector); |
582 | gp_Lin aLine2 (mySecondPoint, aFlyoutVector); |
583 | |
584 | // Get flyout end points |
585 | gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, myFirstPoint) + GetFlyout(), aLine1); |
586 | gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, mySecondPoint) + GetFlyout(), aLine2); |
587 | |
a6eb515f |
588 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
589 | Handle(SelectMgr_EntityOwner) anEmptyOwner; |
590 | myGeom.mySensitiveSegments.Clear(); |
591 | |
d7bffd44 |
592 | gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint); |
a6eb515f |
593 | |
d7bffd44 |
594 | // For extensions we need to know arrow size, text size and extension size: get it from aspect |
595 | Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length(); |
596 | Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); |
a6eb515f |
597 | |
a6eb515f |
598 | if (!myIsValueCustom) |
599 | { |
600 | computeValue(); |
601 | } |
602 | |
603 | TCollection_ExtendedString aValueString; |
604 | Standard_Real aTextLength; |
605 | getTextWidthAndString (aTextLength, aValueString); |
606 | |
d7bffd44 |
607 | // Handle user-defined and automatic arrow placement |
608 | bool isArrowsExternal = false; |
609 | switch (aDimensionAspect->ArrowOrientation()) |
a6eb515f |
610 | { |
d7bffd44 |
611 | case Prs3d_DAO_External: isArrowsExternal = true; break; |
612 | case Prs3d_DAO_Internal: isArrowsExternal = false; break; |
613 | case Prs3d_DAO_Fit: |
a6eb515f |
614 | { |
d7bffd44 |
615 | Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); |
616 | Standard_Real anArrowsWidth = isOneSideDimension ? anArrowLength : 2.0 * anArrowLength; |
617 | isArrowsExternal = aDimensionWidth < aTextLength + anArrowsWidth; |
618 | break; |
a6eb515f |
619 | } |
620 | } |
a6eb515f |
621 | |
622 | // Arrows positions and directions |
d7bffd44 |
623 | gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed(); |
624 | gp_Dir aSecondArrowDir = aDimensionLine.Direction(); |
625 | gp_Dir aFirstExtensionDir = aDimensionLine.Direction().Reversed(); |
626 | gp_Dir aSecondExtensionDir = aDimensionLine.Direction(); |
627 | |
628 | gp_Pnt aFirstArrowBegin (0.0, 0.0, 0.0); |
629 | gp_Pnt aFirstArrowEnd (0.0, 0.0, 0.0); |
630 | gp_Pnt aSecondArrowBegin (0.0, 0.0, 0.0); |
631 | gp_Pnt aSecondArrowEnd (0.0, 0.0, 0.0); |
a6eb515f |
632 | |
d7bffd44 |
633 | if (isArrowsExternal) |
a6eb515f |
634 | { |
635 | aFirstArrowDir.Reverse(); |
636 | aSecondArrowDir.Reverse(); |
a6eb515f |
637 | } |
d7bffd44 |
638 | |
639 | aFirstArrowBegin = aLineBegPoint; |
640 | aSecondArrowBegin = aLineEndPoint; |
641 | aFirstArrowEnd = aLineBegPoint.Translated (-gp_Vec (aFirstArrowDir).Scaled (anArrowLength)); |
642 | aSecondArrowEnd = aLineEndPoint.Translated (-gp_Vec (aSecondArrowDir).Scaled (anArrowLength)); |
643 | |
644 | gp_Pnt aCenterLineBegin = isArrowsExternal |
645 | ? aLineBegPoint : aFirstArrowEnd; |
646 | |
647 | gp_Pnt aCenterLineEnd = isArrowsExternal || isOneSideDimension |
648 | ? aLineEndPoint : aSecondArrowEnd; |
649 | |
650 | Standard_Integer aLabelPosition = LabelPosition_None; |
651 | |
652 | // Handle user-defined and automatic text placement |
653 | switch (aDimensionAspect->TextHorizontalPosition()) |
a6eb515f |
654 | { |
d7bffd44 |
655 | case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break; |
656 | case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break; |
657 | case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break; |
658 | case Prs3d_DTHP_Fit: |
659 | { |
660 | Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); |
661 | Standard_Real anArrowsWidth = isOneSideDimension ? anArrowLength : 2.0 * anArrowLength; |
662 | Standard_Real aContentWidth = isArrowsExternal ? aTextLength : aTextLength + anArrowsWidth; |
663 | |
664 | aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; |
665 | break; |
666 | } |
a6eb515f |
667 | } |
668 | |
d7bffd44 |
669 | switch (aDimensionAspect->TextVerticalPosition()) |
a6eb515f |
670 | { |
d7bffd44 |
671 | case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break; |
672 | case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break; |
673 | case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break; |
a6eb515f |
674 | } |
675 | |
d7bffd44 |
676 | switch (aLabelPosition & LabelPosition_HMask) |
a6eb515f |
677 | { |
d7bffd44 |
678 | // ------------------------------------------------------------------------ // |
679 | // CENTER // |
680 | // -------------------------------------------------------------------------// |
681 | |
682 | case LabelPosition_HCenter: |
a6eb515f |
683 | { |
d7bffd44 |
684 | // add label on dimension or extension line to presentation |
685 | Prs3d_Root::NewGroup (thePresentation); |
a6eb515f |
686 | |
d7bffd44 |
687 | gp_Vec aTextDir (aLineBegPoint, aLineEndPoint); |
688 | |
689 | myGeom.myTextPosition = gp_XYZ (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5; |
a6eb515f |
690 | |
a6eb515f |
691 | Standard_Real aTextWidth = drawText (thePresentation, |
d7bffd44 |
692 | myIsTextReversed ? -aTextDir : aTextDir, |
a6eb515f |
693 | aValueString, |
d7bffd44 |
694 | theMode, |
695 | aLabelPosition); |
a6eb515f |
696 | |
d7bffd44 |
697 | if (theMode == AIS_DDM_Text) |
a6eb515f |
698 | { |
d7bffd44 |
699 | break; |
a6eb515f |
700 | } |
d7bffd44 |
701 | |
702 | Standard_Real aLabelMargin = |
703 | aDimensionAspect->IsText3d() ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN : 0.0; |
704 | |
705 | Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center |
706 | && aDimensionAspect->IsText3d(); |
707 | |
708 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2); |
709 | |
710 | // compute dimension continuous or sectioned dimension line |
711 | if (isLineBreak) |
a6eb515f |
712 | { |
d7bffd44 |
713 | Standard_Real aPTextPosition = ElCLib::Parameter (aDimensionLine, myGeom.myTextPosition); |
714 | gp_Pnt aSection1Beg = aCenterLineBegin; |
715 | gp_Pnt aSection1End = ElCLib::Value (aPTextPosition - aLabelMargin - (aTextWidth * 0.5), aDimensionLine); |
716 | gp_Pnt aSection2Beg = ElCLib::Value (aPTextPosition + aLabelMargin + (aTextWidth * 0.5), aDimensionLine); |
717 | gp_Pnt aSection2End = aCenterLineEnd; |
718 | |
719 | aPrimSegments->AddVertex (aSection1Beg); |
720 | aPrimSegments->AddVertex (aSection1End); |
721 | aPrimSegments->AddVertex (aSection2Beg); |
722 | aPrimSegments->AddVertex (aSection2End); |
723 | |
724 | myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aSection1Beg, aSection1End)); |
725 | myGeom.mySensitiveSegments.Append (new Select3D_SensitiveSegment (anEmptyOwner, aSection2Beg, aSection2End)); |
a6eb515f |
726 | } |
d7bffd44 |
727 | else |
a6eb515f |
728 | { |
d7bffd44 |
729 | aPrimSegments->AddVertex (aCenterLineBegin); |
730 | aPrimSegments->AddVertex (aCenterLineEnd); |
a6eb515f |
731 | |
d7bffd44 |
732 | myGeom.mySensitiveSegments.Append ( |
733 | new Select3D_SensitiveSegment (anEmptyOwner, aCenterLineBegin, aCenterLineEnd)); |
734 | } |
a6eb515f |
735 | |
d7bffd44 |
736 | // set text label justification |
737 | Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM; |
738 | switch (aLabelPosition & LabelPosition_VMask) |
739 | { |
740 | case LabelPosition_Above : |
741 | case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break; |
742 | case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break; |
743 | } |
744 | aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton); |
a6eb515f |
745 | |
746 | // Main dimension line, short extension |
d7bffd44 |
747 | if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All) |
a6eb515f |
748 | { |
d7bffd44 |
749 | Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_True); |
750 | } |
751 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
752 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments); |
753 | if (!aDimensionAspect->IsText3d() && theMode == AIS_DDM_All) |
754 | { |
755 | Prs3d_Root::CurrentGroup (thePresentation)->SetStencilTestOptions (Standard_False); |
756 | } |
757 | |
758 | // add arrows to presentation |
759 | Prs3d_Root::NewGroup (thePresentation); |
760 | |
761 | drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir); |
762 | if (!isOneSideDimension) |
763 | { |
764 | drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir); |
765 | } |
766 | |
767 | if (!isArrowsExternal) |
768 | { |
769 | break; |
770 | } |
771 | |
772 | // add arrow extension lines to presentation |
773 | Prs3d_Root::NewGroup (thePresentation); |
774 | |
775 | drawExtension (thePresentation, anExtensionSize, |
776 | aFirstArrowEnd, aFirstExtensionDir, |
777 | THE_EMPTY_LABEL, theMode, LabelPosition_None); |
778 | if (!isOneSideDimension) |
779 | { |
780 | drawExtension (thePresentation, anExtensionSize, |
781 | aSecondArrowEnd, aSecondExtensionDir, |
782 | THE_EMPTY_LABEL, theMode, LabelPosition_None); |
a6eb515f |
783 | } |
1d7ca641 |
784 | |
785 | break; |
a6eb515f |
786 | } |
d7bffd44 |
787 | // ------------------------------------------------------------------------ // |
788 | // LEFT // |
789 | // -------------------------------------------------------------------------// |
790 | |
791 | case LabelPosition_Left: |
a6eb515f |
792 | { |
d7bffd44 |
793 | // add label on dimension or extension line to presentation |
794 | Prs3d_Root::NewGroup (thePresentation); |
a6eb515f |
795 | |
a6eb515f |
796 | // Left extension with the text |
d7bffd44 |
797 | drawExtension (thePresentation, anExtensionSize, |
798 | isArrowsExternal ? aFirstArrowEnd : aLineBegPoint, |
799 | aFirstExtensionDir, |
800 | aValueString, |
801 | theMode, |
802 | aLabelPosition); |
803 | |
804 | if (theMode == AIS_DDM_Text) |
805 | { |
806 | break; |
807 | } |
808 | |
809 | // add central dimension line |
810 | Prs3d_Root::NewGroup (thePresentation); |
811 | |
812 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2); |
813 | aPrimSegments->AddVertex (aCenterLineBegin); |
814 | aPrimSegments->AddVertex (aCenterLineEnd); |
815 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
816 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments); |
817 | |
818 | myGeom.mySensitiveSegments.Append ( |
819 | new Select3D_SensitiveSegment (anEmptyOwner, aCenterLineBegin, aCenterLineEnd)); |
a6eb515f |
820 | |
d7bffd44 |
821 | // add arrows to presentation |
822 | Prs3d_Root::NewGroup (thePresentation); |
a6eb515f |
823 | |
d7bffd44 |
824 | drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir); |
a6eb515f |
825 | if (!isOneSideDimension) |
826 | { |
d7bffd44 |
827 | drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir); |
a6eb515f |
828 | } |
d7bffd44 |
829 | |
830 | if (!isArrowsExternal || isOneSideDimension) |
a6eb515f |
831 | { |
d7bffd44 |
832 | break; |
a6eb515f |
833 | } |
d7bffd44 |
834 | |
835 | // add extension lines for external arrows |
836 | Prs3d_Root::NewGroup (thePresentation); |
837 | |
838 | drawExtension (thePresentation, anExtensionSize, |
839 | aSecondArrowEnd, aSecondExtensionDir, |
840 | THE_EMPTY_LABEL, theMode, LabelPosition_None); |
841 | |
a6eb515f |
842 | break; |
843 | } |
d7bffd44 |
844 | // ------------------------------------------------------------------------ // |
845 | // RIGHT // |
846 | // -------------------------------------------------------------------------// |
847 | |
848 | case LabelPosition_Right: |
a6eb515f |
849 | { |
d7bffd44 |
850 | // add label on dimension or extension line to presentation |
851 | Prs3d_Root::NewGroup (thePresentation); |
852 | |
853 | // Right extension with text |
854 | drawExtension (thePresentation, anExtensionSize, |
855 | isArrowsExternal ? aSecondArrowEnd : aSecondArrowBegin, |
856 | aSecondExtensionDir, |
857 | aValueString, |
858 | theMode, |
859 | aLabelPosition); |
860 | |
861 | if (theMode == AIS_DDM_Text) |
a6eb515f |
862 | { |
d7bffd44 |
863 | break; |
a6eb515f |
864 | } |
865 | |
d7bffd44 |
866 | // add central dimension line |
867 | Prs3d_Root::NewGroup (thePresentation); |
a6eb515f |
868 | |
d7bffd44 |
869 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2); |
870 | aPrimSegments->AddVertex (aCenterLineBegin); |
871 | aPrimSegments->AddVertex (aCenterLineEnd); |
872 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
873 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments); |
a6eb515f |
874 | |
d7bffd44 |
875 | myGeom.mySensitiveSegments.Append ( |
876 | new Select3D_SensitiveSegment (anEmptyOwner, aCenterLineBegin, aCenterLineEnd)); |
877 | |
878 | // add arrows to presentation |
879 | Prs3d_Root::NewGroup (thePresentation); |
880 | |
881 | drawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir); |
882 | if (!isOneSideDimension) |
a6eb515f |
883 | { |
d7bffd44 |
884 | drawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir); |
885 | } |
a6eb515f |
886 | |
d7bffd44 |
887 | if (!isArrowsExternal || isOneSideDimension) |
888 | { |
889 | break; |
a6eb515f |
890 | } |
d7bffd44 |
891 | |
892 | // add extension lines for external arrows |
893 | Prs3d_Root::NewGroup (thePresentation); |
894 | |
895 | drawExtension (thePresentation, anExtensionSize, |
896 | aFirstArrowEnd, aFirstExtensionDir, |
897 | THE_EMPTY_LABEL, theMode, LabelPosition_None); |
a6eb515f |
898 | break; |
899 | } |
900 | } |
901 | |
d7bffd44 |
902 | // add flyout lines to presentation |
903 | if (theMode == AIS_DDM_All) |
904 | { |
905 | Prs3d_Root::NewGroup (thePresentation); |
906 | |
907 | Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments(4); |
908 | aPrimSegments->AddVertex (myFirstPoint); |
909 | aPrimSegments->AddVertex (aLineBegPoint); |
910 | |
911 | aPrimSegments->AddVertex (mySecondPoint); |
912 | aPrimSegments->AddVertex (aLineEndPoint); |
913 | |
914 | Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); |
915 | Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect()); |
916 | Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments); |
917 | } |
918 | |
a6eb515f |
919 | setComputed (Standard_True); |
920 | } |
921 | |
922 | //======================================================================= |
923 | //function : SetFirstPoint |
924 | //purpose : |
925 | //======================================================================= |
a6eb515f |
926 | void AIS_Dimension::SetFirstPoint (const gp_Pnt& thePoint) |
927 | { |
928 | myFirstPoint = thePoint; |
929 | } |
930 | |
931 | //======================================================================= |
932 | //function : SetSecondPoint |
933 | //purpose : |
934 | //======================================================================= |
a6eb515f |
935 | void AIS_Dimension::SetSecondPoint (const gp_Pnt& thePoint) |
936 | { |
937 | mySecondPoint = thePoint; |
938 | } |
939 | |
940 | //======================================================================= |
941 | //function : Type |
942 | //purpose : |
943 | //======================================================================= |
a6eb515f |
944 | AIS_KindOfInteractive AIS_Dimension::Type() const |
945 | { |
946 | return AIS_KOI_Relation; |
947 | } |
948 | |
949 | //======================================================================= |
950 | //function : circleFromPlanarFace |
951 | //purpose : if possible computes circle from planar face |
952 | //======================================================================= |
a6eb515f |
953 | Standard_Boolean AIS_Dimension::circleFromPlanarFace (const TopoDS_Face& theFace, |
954 | Handle(Geom_Curve)& theCurve, |
955 | gp_Pnt & theFirstPoint, |
956 | gp_Pnt & theLastPoint) |
957 | { |
958 | TopExp_Explorer anIt (theFace, TopAbs_EDGE); |
959 | for ( ; anIt.More(); anIt.Next()) |
960 | { |
961 | TopoDS_Edge aCurEdge = TopoDS::Edge (anIt.Current()); |
962 | if (AIS::ComputeGeometry (aCurEdge, theCurve, theFirstPoint, theLastPoint)) |
963 | { |
964 | if (theCurve->IsInstance (STANDARD_TYPE(Geom_Circle))) |
965 | { |
966 | return Standard_True; |
967 | } |
968 | } |
969 | } |
970 | return Standard_False; |
971 | } |
972 | |
973 | //======================================================================= |
974 | //function : initCircularDimension |
975 | //purpose : if it's possible computes circle from planar face |
976 | //======================================================================= |
a6eb515f |
977 | Standard_Boolean AIS_Dimension::initCircularDimension (const TopoDS_Shape& theShape, |
978 | gp_Circ& theCircle, |
979 | gp_Pnt& theMiddleArcPoint, |
980 | gp_Pnt& theOppositeDiameterPoint) |
981 | { |
982 | gp_Pln aPln; |
983 | Handle(Geom_Surface) aBasisSurf; |
984 | AIS_KindOfSurface aSurfType = AIS_KOS_OtherSurface; |
985 | gp_Pnt aFirstPoint, aLastPoint; |
986 | Standard_Real anOffset = 0.0; |
987 | Standard_Real aFirstParam = 0.0; |
988 | Standard_Real aLastParam = 0.0; |
989 | Standard_Boolean isAnArc = Standard_False; |
990 | |
991 | if (theShape.ShapeType() == TopAbs_FACE) |
992 | { |
993 | AIS::GetPlaneFromFace (TopoDS::Face (theShape), aPln, aBasisSurf, aSurfType, anOffset); |
994 | |
995 | if (aSurfType == AIS_KOS_Plane) |
996 | { |
997 | Handle(Geom_Curve) aCurve; |
998 | if (!circleFromPlanarFace (TopoDS::Face (theShape), aCurve, aFirstPoint, aLastPoint)) |
999 | { |
1000 | Standard_ConstructionError::Raise ("AIS_Dimension:: Curve is not a circle or is Null") ; |
1001 | return Standard_False; |
1002 | } |
1003 | |
1004 | theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); |
1005 | isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion())); |
1006 | } |
1007 | else |
1008 | { |
1009 | gp_Pnt aCurPos; |
1010 | BRepAdaptor_Surface aSurf1 (TopoDS::Face (theShape)); |
1011 | Standard_Real aFirstU = aSurf1.FirstUParameter(); |
1012 | Standard_Real aLastU = aSurf1.LastUParameter(); |
1013 | Standard_Real aFirstV = aSurf1.FirstVParameter(); |
1014 | Standard_Real aLastV = aSurf1.LastVParameter(); |
1015 | Standard_Real aMidU = (aFirstU + aLastU) * 0.5; |
1016 | Standard_Real aMidV = (aFirstV + aLastV) * 0.5; |
1017 | aSurf1.D0(aMidU, aMidV, aCurPos); |
1018 | Handle (Adaptor3d_HCurve) aBasisCurve; |
1019 | Standard_Boolean isExpectedType = Standard_False; |
1020 | if (aSurfType == AIS_KOS_Cylinder) |
1021 | { |
1022 | isExpectedType = Standard_True; |
1023 | } |
1024 | else |
1025 | { |
1026 | if (aSurfType == AIS_KOS_Revolution) |
1027 | { |
1028 | aBasisCurve = aSurf1.BasisCurve(); |
1029 | if (aBasisCurve->GetType() == GeomAbs_Line) |
1030 | { |
1031 | isExpectedType = Standard_True; |
1032 | } |
1033 | } |
1034 | else if (aSurfType == AIS_KOS_Extrusion) |
1035 | { |
1036 | aBasisCurve = aSurf1.BasisCurve(); |
1037 | if (aBasisCurve->GetType() == GeomAbs_Circle) |
1038 | { |
1039 | isExpectedType = Standard_True; |
1040 | } |
1041 | } |
1042 | } |
1043 | |
1044 | if (!isExpectedType) |
1045 | { |
1046 | Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of surface") ; |
1047 | return Standard_False; |
1048 | } |
1049 | Handle(Geom_Curve) aCurve; |
1050 | aCurve = aBasisSurf->VIso(aMidV); |
1051 | if (aCurve->DynamicType() == STANDARD_TYPE (Geom_Circle)) |
1052 | { |
1053 | theCircle = Handle(Geom_Circle)::DownCast (aCurve)->Circ(); |
1054 | } |
1055 | else if (aCurve->DynamicType() == STANDARD_TYPE (Geom_TrimmedCurve)) |
1056 | { |
1057 | Handle(Geom_TrimmedCurve) aTrimmedCurve = Handle(Geom_TrimmedCurve)::DownCast (aCurve); |
1058 | aFirstU = aTrimmedCurve->FirstParameter(); |
1059 | aLastU = aTrimmedCurve->LastParameter(); |
1060 | if (aTrimmedCurve->DynamicType() == STANDARD_TYPE (Geom_Circle)) |
1061 | { |
1062 | theCircle = Handle(Geom_Circle)::DownCast(aTrimmedCurve)->Circ(); |
1063 | } |
1064 | } |
1065 | else |
1066 | { |
1067 | // Compute a circle from 3 points on "aCurve" |
1068 | gp_Pnt aP1, aP2; |
1069 | aSurf1.D0 (aFirstU, aMidV, aP1); |
1070 | aSurf1.D0 (aLastU, aMidV, aP2); |
1071 | GC_MakeCircle aMkCirc (aP1, aCurPos, aP2); |
1072 | theCircle = aMkCirc.Value()->Circ(); |
1073 | } |
1074 | |
1075 | gp_Vec aVec = gp_Vec (theCircle.Location(), aCurPos).Normalized(); |
1076 | aFirstPoint = ElCLib::Value (aFirstU, theCircle); |
1077 | aLastPoint = ElCLib::Value (aLastU, theCircle); |
1078 | } |
1079 | } |
1080 | else // TopAbs_EDGE | TopAbs_WIRE |
1081 | { |
1082 | TopoDS_Edge anEdge; |
1083 | if (theShape.ShapeType() == TopAbs_WIRE) |
1084 | { |
1085 | TopExp_Explorer anIt (theShape, TopAbs_EDGE); |
1086 | if (anIt.More()) |
1087 | { |
1088 | anEdge = TopoDS::Edge (anIt.Current()); |
1089 | } |
1090 | } |
1091 | else if (theShape.ShapeType() == TopAbs_EDGE) |
1092 | { |
1093 | anEdge = TopoDS::Edge (theShape); |
1094 | } |
1095 | else // Unexpected type of shape |
1096 | { |
1097 | Standard_ConstructionError::Raise ("AIS_Dimension:: Unexpected type of shape"); |
1098 | return Standard_False; |
1099 | } |
1100 | BRepAdaptor_Curve anAdaptedCurve (anEdge); |
1101 | if (!anAdaptedCurve.GetType() == GeomAbs_Circle) |
1102 | { |
1103 | return Standard_False; |
1104 | } |
1105 | theCircle = anAdaptedCurve.Circle(); |
1106 | aFirstPoint = anAdaptedCurve.Value (anAdaptedCurve.FirstParameter()); |
1107 | aLastPoint = anAdaptedCurve.Value (anAdaptedCurve.LastParameter()); |
1108 | } |
1109 | // Get <theMiddleArcPoint> and <theOppositeDiameterPoint> values from <theCircle> |
1110 | isAnArc = !(aFirstPoint.IsEqual (aLastPoint, Precision::Confusion())); |
1111 | gp_Pnt aCenter = theCircle.Location(); |
1112 | if (!isAnArc) |
1113 | { |
1114 | // Circle |
1115 | gp_Dir anXDir = theCircle.XAxis().Direction(); |
1116 | theMiddleArcPoint = aCenter.Translated (gp_Vec (anXDir) * theCircle.Radius()); |
1117 | theOppositeDiameterPoint = aCenter.Translated (-gp_Vec (anXDir) * theCircle.Radius()); |
1118 | } |
1119 | else |
1120 | { |
1121 | // Arc |
1122 | aFirstParam = ElCLib::Parameter (theCircle, aFirstPoint); |
1123 | aLastParam = ElCLib::Parameter (theCircle, aLastPoint); |
1124 | if (aFirstParam > aLastParam) |
1125 | { |
1126 | aFirstParam -= 2.0 * M_PI; |
1127 | } |
1128 | Standard_Real aParCurPos = (aFirstParam + aLastParam) * 0.5; |
1129 | gp_Vec aVec = gp_Vec (aCenter, ElCLib::Value (aParCurPos, theCircle)).Normalized () * theCircle.Radius (); |
1130 | theMiddleArcPoint = aCenter.Translated (aVec); |
1131 | theOppositeDiameterPoint = aCenter.Translated (-aVec); |
1132 | } |
1133 | |
1134 | return Standard_True; |
1135 | } |
1136 | |
1137 | //======================================================================= |
1138 | //function : SetDisplaySpecialSymbol |
1139 | //purpose : specifies dimension special symbol display options |
1140 | //======================================================================= |
a6eb515f |
1141 | void AIS_Dimension::SetDisplaySpecialSymbol (const AIS_DisplaySpecialSymbol theDisplaySpecSymbol) |
1142 | { |
1143 | myDisplaySpecialSymbol = theDisplaySpecSymbol; |
1144 | } |
1145 | |
1146 | //======================================================================= |
1147 | //function : DisplaySpecialSymbol |
1148 | //purpose : shows dimension special symbol display options |
1149 | //======================================================================= |
a6eb515f |
1150 | AIS_DisplaySpecialSymbol AIS_Dimension::DisplaySpecialSymbol() const |
1151 | { |
1152 | return myDisplaySpecialSymbol; |
1153 | } |
1154 | |
1155 | //======================================================================= |
1156 | //function : SetSpecialSymbol |
1157 | //purpose : specifies special symbol |
1158 | //======================================================================= |
a6eb515f |
1159 | void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol) |
1160 | { |
1161 | mySpecialSymbol = theSpecialSymbol; |
1162 | } |
1163 | |
1164 | //======================================================================= |
1165 | //function : SpecialSymbol |
1166 | //purpose : returns special symbol |
1167 | //======================================================================= |
a6eb515f |
1168 | Standard_ExtCharacter AIS_Dimension::SpecialSymbol() const |
1169 | { |
1170 | return mySpecialSymbol; |
1171 | } |
1172 | |
1173 | //======================================================================= |
1174 | //function : IsUnitsDisplayed |
1175 | //purpose : shows if Units are to be displayed along with dimension value |
1176 | //======================================================================= |
a6eb515f |
1177 | Standard_Boolean AIS_Dimension::IsUnitsDisplayed() const |
1178 | { |
1179 | return myToDisplayUnits; |
1180 | } |
1181 | |
1182 | //======================================================================= |
1183 | //function : MakeUnitsDisplayed |
1184 | //purpose : sets to display units along with the dimension value or no |
1185 | //======================================================================= |
a6eb515f |
1186 | void AIS_Dimension::MakeUnitsDisplayed (const Standard_Boolean toDisplayUnits) |
1187 | { |
1188 | myToDisplayUnits = toDisplayUnits; |
1189 | } |
1190 | |
1191 | //======================================================================= |
1192 | //function : MakeUnitsDisplayed |
1193 | //purpose : returns the current type of units |
1194 | //======================================================================= |
a6eb515f |
1195 | TCollection_AsciiString AIS_Dimension::UnitsQuantity() const |
1196 | { |
1197 | return myUnitsQuantity; |
1198 | } |
1199 | |
1200 | //======================================================================= |
1201 | //function : SetUnitsQuantity |
1202 | //purpose : sets the current type of units |
1203 | //======================================================================= |
a6eb515f |
1204 | void AIS_Dimension::SetUnitsQuantity (const TCollection_AsciiString& theUnitsQuantity) |
1205 | { |
1206 | myUnitsQuantity = theUnitsQuantity; |
1207 | } |
1208 | |
1209 | //======================================================================= |
1210 | //function : ModelUnits |
1211 | //purpose : returns the current model units |
1212 | //======================================================================= |
a6eb515f |
1213 | TCollection_AsciiString AIS_Dimension::ModelUnits() const |
1214 | { |
1215 | return myModelUnits; |
1216 | } |
1217 | |
1218 | //======================================================================= |
1219 | //function : SetModelUnits |
1220 | //purpose : sets the current model units |
1221 | //======================================================================= |
a6eb515f |
1222 | void AIS_Dimension::SetModelUnits (const TCollection_AsciiString& theUnits) |
1223 | { |
1224 | myModelUnits = theUnits; |
1225 | } |
1226 | |
1227 | //======================================================================= |
1228 | //function : DisplayUnits |
1229 | //purpose : returns the current display units |
1230 | //======================================================================= |
a6eb515f |
1231 | TCollection_AsciiString AIS_Dimension::DisplayUnits() const |
1232 | { |
1233 | return myDisplayUnits; |
1234 | } |
1235 | |
1236 | //======================================================================= |
1237 | //function : SetDisplayUnits |
1238 | //purpose : sets the current display units |
1239 | //======================================================================= |
a6eb515f |
1240 | void AIS_Dimension::SetDisplayUnits (const TCollection_AsciiString& theUnits) |
1241 | { |
1242 | myDisplayUnits = theUnits; |
1243 | } |
1244 | |
1245 | //======================================================================= |
1246 | //function : isComputed |
1247 | //purpose : |
1248 | //======================================================================= |
a6eb515f |
1249 | Standard_Boolean AIS_Dimension::isComputed() const |
1250 | { |
1251 | return myGeom.myIsComputed; |
1252 | } |
1253 | |
1254 | //======================================================================= |
1255 | //function : setComputed |
1256 | //purpose : |
1257 | //======================================================================= |
a6eb515f |
1258 | void AIS_Dimension::setComputed (Standard_Boolean isComputed) |
1259 | { |
1260 | myGeom.myIsComputed = isComputed; |
1261 | } |
1262 | |
1263 | //======================================================================= |
1264 | //function : textPosition |
1265 | //purpose : |
1266 | //======================================================================= |
a6eb515f |
1267 | gp_Pnt AIS_Dimension::textPosition() const |
1268 | { |
1269 | return myGeom.myTextPosition; |
1270 | } |
1271 | |
1272 | //======================================================================= |
1273 | //function : setTextPosition |
1274 | //purpose : |
1275 | //======================================================================= |
a6eb515f |
1276 | void AIS_Dimension::setTextPosition (const gp_Pnt thePosition) |
1277 | { |
1278 | myGeom.myTextPosition = thePosition; |
1279 | } |
1280 | |
1281 | //======================================================================= |
1282 | //function : resetGeom |
1283 | //purpose : |
1284 | //======================================================================= |
a6eb515f |
1285 | void AIS_Dimension::resetGeom() |
1286 | { |
1287 | setComputed (Standard_False); |
1288 | } |
1289 | |
1290 | //======================================================================= |
1291 | //function : IsTextReversed |
1292 | //purpose : |
1293 | //======================================================================= |
a6eb515f |
1294 | Standard_Boolean AIS_Dimension::IsTextReversed() const |
1295 | { |
1296 | return myIsTextReversed; |
1297 | } |
1298 | |
1299 | //======================================================================= |
1300 | //function : MakeTextReversed |
1301 | //purpose : |
1302 | //======================================================================= |
a6eb515f |
1303 | void AIS_Dimension::MakeTextReversed (const Standard_Boolean isTextReversed) |
1304 | { |
1305 | myIsTextReversed = isTextReversed; |
1306 | } |
1307 | |
1308 | //======================================================================= |
1309 | //function : SetSelToleranceForText2d |
1310 | //purpose : |
1311 | //======================================================================= |
a6eb515f |
1312 | void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol) |
1313 | { |
1314 | myGeom.mySelToleranceForText2d = theTol; |
1315 | } |
1316 | |
1317 | //======================================================================= |
1318 | //function : SelToleranceForText2d |
1319 | //purpose : |
1320 | //======================================================================= |
a6eb515f |
1321 | Standard_Real AIS_Dimension::SelToleranceForText2d() const |
1322 | { |
1323 | return myGeom.mySelToleranceForText2d; |
1324 | } |
1325 | |
62b6361a |
1326 | //======================================================================= |
1327 | //function : SetFlyout |
d7bffd44 |
1328 | //purpose : |
62b6361a |
1329 | //======================================================================= |
62b6361a |
1330 | void AIS_Dimension::SetFlyout (const Standard_Real theFlyout) |
1331 | { |
d7bffd44 |
1332 | if (myFlyout == theFlyout) |
1333 | { |
1334 | return; |
1335 | } |
62b6361a |
1336 | |
d7bffd44 |
1337 | myFlyout = theFlyout; |
1338 | SetToUpdate(); |
62b6361a |
1339 | } |
1340 | |
1341 | //======================================================================= |
1342 | //function : computeFlyoutSelection |
1343 | //purpose : computes selection for flyouts |
1344 | //======================================================================= |
62b6361a |
1345 | void AIS_Dimension::computeFlyoutSelection (const Handle(SelectMgr_Selection)& theSelection, |
d7bffd44 |
1346 | const Handle(AIS_DimensionOwner)& theOwner) |
62b6361a |
1347 | { |
d7bffd44 |
1348 | //Count flyout direction |
1349 | gp_Ax1 aWorkingPlaneNormal = GetWorkingPlane().Axis(); |
1350 | gp_Dir aTargetPointsVector = gce_MakeDir (myFirstPoint, mySecondPoint); |
1351 | |
1352 | // Count a flyout direction vector. |
1353 | gp_Dir aFlyoutVector = aWorkingPlaneNormal.Direction()^aTargetPointsVector; |
1354 | |
1355 | // Create lines for layouts |
1356 | gp_Lin aLine1 (myFirstPoint, aFlyoutVector); |
1357 | gp_Lin aLine2 (mySecondPoint, aFlyoutVector); |
1358 | |
1359 | // Get flyout end points |
1360 | gp_Pnt aFlyoutEnd1 = ElCLib::Value (ElCLib::Parameter (aLine1, myFirstPoint) + GetFlyout(), aLine1); |
1361 | gp_Pnt aFlyoutEnd2 = ElCLib::Value (ElCLib::Parameter (aLine2, mySecondPoint) + GetFlyout(), aLine2); |
1362 | |
1363 | // Fill sensitive entity for flyouts |
1364 | Handle(Select3D_SensitiveGroup) aSensitiveEntity = new Select3D_SensitiveGroup (theOwner); |
1365 | aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, myFirstPoint, aFlyoutEnd1)); |
1366 | aSensitiveEntity->Add (new Select3D_SensitiveSegment (theOwner, mySecondPoint, aFlyoutEnd2)); |
1367 | theSelection->Add (aSensitiveEntity); |
62b6361a |
1368 | } |
1369 | |
a6eb515f |
1370 | //======================================================================= |
1371 | //function : ComputeSelection |
1372 | //purpose : |
1373 | //======================================================================= |
a6eb515f |
1374 | void AIS_Dimension::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, |
1375 | const Standard_Integer theMode) |
1376 | { |
1377 | if (!isComputed()) |
1378 | { |
1379 | return; |
1380 | } |
1381 | |
62b6361a |
1382 | Handle(Select3D_SensitiveGroup) aSensitiveForLine; |
a6eb515f |
1383 | Handle(Select3D_SensitiveEntity) aSensitiveForText; |
1384 | Select3D_ListOfSensitive aSensitiveList; |
1385 | aSensitiveList.Assign (myGeom.mySensitiveSegments); |
1386 | |
1387 | // Full dimension selection |
1388 | Handle(AIS_DimensionOwner) anOwner = new AIS_DimensionOwner (this, AIS_DDM_All, theMode == 0 ? 5 : 6); |
1389 | for (Select3D_ListIteratorOfListOfSensitive anIt (aSensitiveList); anIt.More(); anIt.Next()) |
1390 | { |
1391 | anIt.Value()->Set (anOwner); |
1392 | } |
1393 | aSensitiveForLine = new Select3D_SensitiveGroup (anOwner, aSensitiveList); |
1394 | |
1395 | // Text |
1396 | if (myDrawer->DimensionAspect()->IsText3d()) |
1397 | { |
1398 | aSensitiveForText = new Select3D_SensitiveBox (anOwner,myGeom.myTextBndBox); |
1399 | } |
1400 | else |
1401 | { |
1402 | Handle(Geom_Circle) aSensitiveGeom = new Geom_Circle (gp_Circ (gp_Ax2 (myGeom.myTextPosition, |
1403 | myWorkingPlane.Position().XDirection()), |
1404 | myGeom.mySelToleranceForText2d != 0 |
1405 | ? myGeom.mySelToleranceForText2d : 1.0)); |
1406 | aSensitiveForText = new Select3D_SensitiveCircle (anOwner, aSensitiveGeom, Standard_True); |
1407 | } |
1408 | if (theMode > 0) |
1409 | { |
1410 | anOwner->SetDisplayMode (AIS_DDM_Line); |
1411 | Handle(AIS_DimensionOwner) aTextOwner = new AIS_DimensionOwner (this, AIS_DDM_Text, 7); |
1412 | aSensitiveForText->Set (aTextOwner); |
1413 | } |
62b6361a |
1414 | else |
d7bffd44 |
1415 | { |
62b6361a |
1416 | computeFlyoutSelection (theSelection, anOwner); |
d7bffd44 |
1417 | } |
a6eb515f |
1418 | |
1419 | theSelection->Add (aSensitiveForLine); |
1420 | theSelection->Add (aSensitiveForText); |
1421 | } |