0024351: Test cases for AIS dimension presentations to check arrow orientation, text...
[occt.git] / src / AIS / AIS_Dimension.cxx
CommitLineData
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
76IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
77IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
78
d7bffd44 79namespace
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 90AIS_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 116Standard_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 125void 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 136void AIS_Dimension::countDefaultPlane()
137{
138}
139
140//=======================================================================
141//function : GetWorkingPlane
142//purpose :
143//=======================================================================
a6eb515f 144const gp_Pln& AIS_Dimension::GetWorkingPlane() const
145{
146 return myWorkingPlane;
147}
148
149//=======================================================================
150//function : SetWorkingPlane
151//purpose :
152//=======================================================================
a6eb515f 153void 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 163void 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 174void AIS_Dimension::resetWorkingPlane (const gp_Pln& theNewDefaultPlane)
175{
176 myDefaultPlane = theNewDefaultPlane;
177 ResetWorkingPlane();
178}
179
180//=======================================================================
181//function : valueInDisplayUnits
182//purpose :
183//=======================================================================
a6eb515f 184Standard_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 195AIS_KindOfDimension AIS_Dimension::KindOfDimension() const
196{
197 return myKindOfDimension;
198}
199
200//=======================================================================
201//function : SetKindOfDimension
202//purpose :
203//=======================================================================
a6eb515f 204void AIS_Dimension::SetKindOfDimension (const AIS_KindOfDimension theKindOfDimension)
205{
206 myKindOfDimension = theKindOfDimension;
207}
208
a6eb515f 209//=======================================================================
210//function : GetValue
211//purpose :
212//=======================================================================
a6eb515f 213Standard_Real AIS_Dimension::GetValue() const
214 {
215 return myValue;
216 }
217
218//=======================================================================
219//function : SetCustomValue
220//purpose :
221//=======================================================================
a6eb515f 222void 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 232void 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 243void 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 254void 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 304void 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 354Standard_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 484void 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 544void AIS_Dimension::SetDimensionAspect (const Handle(Prs3d_DimensionAspect)& theDimensionAspect)
545{
546 myDrawer->SetDimensionAspect (theDimensionAspect);
547}
548
549//=======================================================================
550//function : DimensionAspect
551//purpose :
552//=======================================================================
a6eb515f 553Handle(Prs3d_DimensionAspect) AIS_Dimension::DimensionAspect() const
554{
555 return myDrawer->DimensionAspect();
556}
557
a6eb515f 558//=======================================================================
559//function : drawLinearDimension
560//purpose :
561//=======================================================================
a6eb515f 562void 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 926void AIS_Dimension::SetFirstPoint (const gp_Pnt& thePoint)
927{
928 myFirstPoint = thePoint;
929}
930
931//=======================================================================
932//function : SetSecondPoint
933//purpose :
934//=======================================================================
a6eb515f 935void AIS_Dimension::SetSecondPoint (const gp_Pnt& thePoint)
936{
937 mySecondPoint = thePoint;
938}
939
940//=======================================================================
941//function : Type
942//purpose :
943//=======================================================================
a6eb515f 944AIS_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 953Standard_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 977Standard_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 1141void 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 1150AIS_DisplaySpecialSymbol AIS_Dimension::DisplaySpecialSymbol() const
1151{
1152 return myDisplaySpecialSymbol;
1153}
1154
1155//=======================================================================
1156//function : SetSpecialSymbol
1157//purpose : specifies special symbol
1158//=======================================================================
a6eb515f 1159void AIS_Dimension::SetSpecialSymbol (const Standard_ExtCharacter theSpecialSymbol)
1160{
1161 mySpecialSymbol = theSpecialSymbol;
1162}
1163
1164//=======================================================================
1165//function : SpecialSymbol
1166//purpose : returns special symbol
1167//=======================================================================
a6eb515f 1168Standard_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 1177Standard_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 1186void 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 1195TCollection_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 1204void 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 1213TCollection_AsciiString AIS_Dimension::ModelUnits() const
1214{
1215 return myModelUnits;
1216}
1217
1218//=======================================================================
1219//function : SetModelUnits
1220//purpose : sets the current model units
1221//=======================================================================
a6eb515f 1222void 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 1231TCollection_AsciiString AIS_Dimension::DisplayUnits() const
1232{
1233 return myDisplayUnits;
1234}
1235
1236//=======================================================================
1237//function : SetDisplayUnits
1238//purpose : sets the current display units
1239//=======================================================================
a6eb515f 1240void AIS_Dimension::SetDisplayUnits (const TCollection_AsciiString& theUnits)
1241{
1242 myDisplayUnits = theUnits;
1243}
1244
1245//=======================================================================
1246//function : isComputed
1247//purpose :
1248//=======================================================================
a6eb515f 1249Standard_Boolean AIS_Dimension::isComputed() const
1250{
1251 return myGeom.myIsComputed;
1252}
1253
1254//=======================================================================
1255//function : setComputed
1256//purpose :
1257//=======================================================================
a6eb515f 1258void AIS_Dimension::setComputed (Standard_Boolean isComputed)
1259{
1260 myGeom.myIsComputed = isComputed;
1261}
1262
1263//=======================================================================
1264//function : textPosition
1265//purpose :
1266//=======================================================================
a6eb515f 1267gp_Pnt AIS_Dimension::textPosition() const
1268{
1269 return myGeom.myTextPosition;
1270}
1271
1272//=======================================================================
1273//function : setTextPosition
1274//purpose :
1275//=======================================================================
a6eb515f 1276void AIS_Dimension::setTextPosition (const gp_Pnt thePosition)
1277{
1278 myGeom.myTextPosition = thePosition;
1279}
1280
1281//=======================================================================
1282//function : resetGeom
1283//purpose :
1284//=======================================================================
a6eb515f 1285void AIS_Dimension::resetGeom()
1286{
1287 setComputed (Standard_False);
1288}
1289
1290//=======================================================================
1291//function : IsTextReversed
1292//purpose :
1293//=======================================================================
a6eb515f 1294Standard_Boolean AIS_Dimension::IsTextReversed() const
1295{
1296 return myIsTextReversed;
1297}
1298
1299//=======================================================================
1300//function : MakeTextReversed
1301//purpose :
1302//=======================================================================
a6eb515f 1303void AIS_Dimension::MakeTextReversed (const Standard_Boolean isTextReversed)
1304{
1305 myIsTextReversed = isTextReversed;
1306}
1307
1308//=======================================================================
1309//function : SetSelToleranceForText2d
1310//purpose :
1311//=======================================================================
a6eb515f 1312void AIS_Dimension::SetSelToleranceForText2d (const Standard_Real theTol)
1313{
1314 myGeom.mySelToleranceForText2d = theTol;
1315}
1316
1317//=======================================================================
1318//function : SelToleranceForText2d
1319//purpose :
1320//=======================================================================
a6eb515f 1321Standard_Real AIS_Dimension::SelToleranceForText2d() const
1322{
1323 return myGeom.mySelToleranceForText2d;
1324}
1325
62b6361a 1326//=======================================================================
1327//function : SetFlyout
d7bffd44 1328//purpose :
62b6361a 1329//=======================================================================
62b6361a 1330void 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 1345void 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 1374void 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}