diff --git a/src/AIS/AIS.cdl b/src/AIS/AIS.cdl index f1f9c76ba9..7909dad70f 100644 --- a/src/AIS/AIS.cdl +++ b/src/AIS/AIS.cdl @@ -241,19 +241,23 @@ is KOI_Datum, KOI_Shape, KOI_Object, - KOI_Relation; - --- Purpose: Declares the type of Interactive Object. - -- This is one of the following: - -- - the Datum - -- - the Object - -- - the Relation - -- - the None type. - -- The Datum is the construction element. These include - -- points, lines, axes and planes. The object brings - -- together topological shapes. The Relation includes - -- dimensions and constraints. When the object is of an - -- unknown type, the None type is declared. - + KOI_Relation, + KOI_Dimension; + --- Purpose: Declares the type of Interactive Object. + -- This is one of the following: + -- - the Datum + -- - the Object + -- - the Relation + -- - the Dimension + -- - the None type. + -- The Datum is the construction element. These include + -- points, lines, axes and planes. The object brings + -- together topological shapes. The Relation includes + -- dimensions and constraints. The Dimension includes + -- length, radius, diameter and angle dimensions. + -- When the object is of an unknown type, the None + -- type is declared. + enumeration ClearMode is CM_All, CM_Interactive, diff --git a/src/AIS/AIS_AngleDimension.cxx b/src/AIS/AIS_AngleDimension.cxx index 6b841c8932..b31ed173c8 100644 --- a/src/AIS/AIS_AngleDimension.cxx +++ b/src/AIS/AIS_AngleDimension.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension) @@ -152,7 +153,7 @@ void AIS_AngleDimension::SetMeasuredGeometry (const TopoDS_Edge& theFirstEdge, if (myIsValid && !myIsPlaneCustom) { - myPlane = aComputedPlane; + ComputePlane(); } myIsValid &= CheckPlane (myPlane); @@ -300,7 +301,7 @@ void AIS_AngleDimension::Init() //======================================================================= gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach, const gp_Pnt& theSecondAttach, - const gp_Pnt& theCenter) + const gp_Pnt& theCenter) const { // construct plane where the circle and the arc are located gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter); @@ -583,7 +584,7 @@ Standard_Real AIS_AngleDimension::ComputeValue() const Standard_Real anAngle = aVec2.AngleWithRef (aVec1, GetPlane().Axis().Direction()); - return anAngle > 0.0 ? anAngle : (2.0 * M_PI - anAngle); + return anAngle > 0.0 ? anAngle : (2.0 * M_PI + anAngle); } //======================================================================= @@ -619,31 +620,23 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /* aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; } - gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); - gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); + // Get parameters from aspect or adjust it according with custom text position + Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); + Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition(); + + if (IsTextPositionCustom()) + { + AdjustParameters (myFixedTextPosition,anExtensionSize, aHorisontalTextPos); + } // Handle user-defined and automatic arrow placement - bool isArrowsExternal = false; - switch (aDimensionAspect->ArrowOrientation()) - { - case Prs3d_DAO_External: isArrowsExternal = true; break; - case Prs3d_DAO_Internal: isArrowsExternal = false; break; - case Prs3d_DAO_Fit: - { - gp_Vec anAttachVector (aFirstAttach, aSecondAttach); - Standard_Real aDimensionWidth = anAttachVector.Magnitude(); + Standard_Boolean isArrowsExternal = Standard_False; + Standard_Integer aLabelPosition = LabelPosition_None; - // add margin to ensure a small tail between text and arrow - Standard_Real anArrowMargin = aDimensionAspect->IsText3d() - ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN - : 0.0; + FitTextAlignment (aHorisontalTextPos, aLabelPosition, isArrowsExternal); - Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0; - - isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth; - break; - } - } + gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); + gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); //Arrows positions and directions gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction()); @@ -670,38 +663,9 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /* aFirstArrowEnd = aFirstAttach.Translated (-aFirstArrowVec); aSecondArrowEnd = aSecondAttach.Translated (-aSecondArrowVec); - Standard_Integer aLabelPosition = LabelPosition_None; - - // Handle user-defined and automatic text placement - switch (aDimensionAspect->TextHorizontalPosition()) - { - case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break; - case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break; - case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break; - case Prs3d_DTHP_Fit: - { - gp_Vec anAttachVector (aFirstAttach, aSecondAttach); - Standard_Real aDimensionWidth = anAttachVector.Magnitude(); - Standard_Real anArrowsWidth = anArrowLength * 2.0; - Standard_Real aContentWidth = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth; - - aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; - break; - } - } - - switch (aDimensionAspect->TextVerticalPosition()) - { - case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break; - case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break; - case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break; - } - // Group1: stenciling text and the angle dimension arc Prs3d_Root::NewGroup (thePresentation); - Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); - Standard_Integer aHPosition = aLabelPosition & LabelPosition_HMask; // draw text label @@ -729,7 +693,8 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /* if (theMode == ComputeMode_All || theMode == ComputeMode_Text) { gp_Vec aDimensionDir (aFirstAttach, aSecondAttach); - gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint); + gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition + : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint); gp_Dir aTextDir = aDimensionDir; DrawText (thePresentation, @@ -807,7 +772,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /* if (aHPosition != LabelPosition_Left) { DrawExtension (thePresentation, - anExtensionSize, + aDimensionAspect->ArrowTailSize(), aFirstArrowEnd, aFirstExtensionDir, THE_EMPTY_LABEL_STRING, @@ -819,7 +784,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /* if (aHPosition != LabelPosition_Right) { DrawExtension (thePresentation, - anExtensionSize, + aDimensionAspect->ArrowTailSize(), aSecondArrowEnd, aSecondExtensionDir, THE_EMPTY_LABEL_STRING, @@ -1184,3 +1149,272 @@ Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint, && gp_Vec (theCenterPoint, theFirstPoint).Angle ( gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular(); } + +//======================================================================= +//function : GetTextPosition +//purpose : +//======================================================================= +const gp_Pnt AIS_AngleDimension::GetTextPosition() const +{ + if (!IsValid()) + { + return gp::Origin(); + } + + if (IsTextPositionCustom()) + { + return myFixedTextPosition; + } + + // Counts text position according to the dimension parameters + gp_Pnt aTextPosition (gp::Origin()); + + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + + // Prepare label string and compute its geometrical width + Standard_Real aLabelWidth; + TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); + + gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); + gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); + + // Handle user-defined and automatic arrow placement + Standard_Boolean isArrowsExternal = Standard_False; + Standard_Integer aLabelPosition = LabelPosition_None; + FitTextAlignment (aDimensionAspect->TextHorizontalPosition(), + aLabelPosition, isArrowsExternal); + + // Get text position + switch (aLabelPosition & LabelPosition_HMask) + { + case LabelPosition_HCenter: + { + aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint); + } + break; + case LabelPosition_Left: + { + gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach); + gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach); + Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); + Standard_Real anOffset = isArrowsExternal + ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() + : anExtensionSize; + gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * -anOffset; + aTextPosition = aFirstAttach.Translated (anExtensionVec); + } + break; + case LabelPosition_Right: + { + gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach); + gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach); + Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); + Standard_Real anOffset = isArrowsExternal + ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() + : anExtensionSize; + gp_Vec anExtensionVec = gp_Vec (anExtensionDir) * anOffset; + aTextPosition = aSecondAttach.Translated (anExtensionVec); + } + break; + } + + return aTextPosition; +} + +//======================================================================= +//function : SetTextPosition +//purpose : +//======================================================================= +void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos) +{ + if (!IsValid()) + { + return; + } + + // The text position point for angle dimension should belong to the working plane. + if (!GetPlane().Contains (theTextPos, Precision::Confusion())) + { + Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane."); + } + + myIsTextPositionFixed = Standard_True; + myFixedTextPosition = theTextPos; +} + +//======================================================================= +//function : AdjustAspectParameters +//purpose : +//======================================================================= +void AIS_AngleDimension::AdjustParameters (const gp_Pnt& theTextPos, + Standard_Real& theExtensionSize, + Prs3d_DimensionTextHorizontalPosition& theAlignment) +{ + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); + + // Compute flyout direction vector. + gp_Dir aPlaneNormal = GetPlane().Axis().Direction(); + gp_Dir aTargetPointsDir = gce_MakeDir (myFirstPoint, mySecondPoint); + + // Build circle with radius that is equal to distance from text position to the center point. + Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude(); + + // Set attach points in positive direction of the flyout. + gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * aRadius); + gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * aRadius); + + gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius); + if (!aConstructCircle.IsDone()) + { + return; + } + gp_Circ aCircle = aConstructCircle.Value(); + + // Default values + theExtensionSize = aDimensionAspect->ArrowAspect()->Length(); + theAlignment = Prs3d_DTHP_Center; + + Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach); + Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach); + if (aParamEnd < aParamBeg) + { + Standard_Real aParam = aParamEnd; + aParamEnd = aParamBeg; + aParamBeg = aParam; + } + + ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); + Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos); + + // Horizontal center + if (aTextPar > aParamBeg && aTextPar < aParamEnd) + { + myFlyout = aRadius; + + SetToUpdate(); + return; + } + + aParamBeg += M_PI; + aParamEnd += M_PI; + ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd); + + if (aTextPar > aParamBeg && aTextPar < aParamEnd) + { + myFlyout = -aRadius; + + SetToUpdate(); + return; + } + + // Text on the extensions + gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint); + gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint); + gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos); + gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos); + Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos); + Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos); + + if (aFirstDist <= aSecondDist) + { + aRadius = myCenterPoint.Distance (aFirstTextProj); + Standard_Real aNewExtensionSize = aFirstDist - anArrowLength; + theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize; + + theAlignment = Prs3d_DTHP_Left; + + gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius); + + myFlyout = aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion() + ? -aRadius : aRadius; + } + else + { + aRadius = myCenterPoint.Distance (aSecondTextProj); + + Standard_Real aNewExtensionSize = aSecondDist - anArrowLength; + + theExtensionSize = aNewExtensionSize < 0.0 ? 0.0 : aNewExtensionSize; + + theAlignment = Prs3d_DTHP_Right; + + gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius); + + myFlyout = aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion() + ? -aRadius : aRadius; + } +} + +//======================================================================= +//function : FitTextAlignment +//purpose : +//======================================================================= +void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, + Standard_Integer& theLabelPosition, + Standard_Boolean& theIsArrowsExternal) const +{ + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + + Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length(); + + // Prepare label string and compute its geometrical width + Standard_Real aLabelWidth; + TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); + + // add margins to label width + if (aDimensionAspect->IsText3d()) + { + aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; + } + + gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, myFirstPoint).Normalized() * GetFlyout()); + gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec (myCenterPoint, mySecondPoint).Normalized() * GetFlyout()); + + // Handle user-defined and automatic arrow placement + switch (aDimensionAspect->ArrowOrientation()) + { + case Prs3d_DAO_External: theIsArrowsExternal = true; break; + case Prs3d_DAO_Internal: theIsArrowsExternal = false; break; + case Prs3d_DAO_Fit: + { + gp_Vec anAttachVector (aFirstAttach, aSecondAttach); + Standard_Real aDimensionWidth = anAttachVector.Magnitude(); + + // Add margin to ensure a small tail between text and arrow + Standard_Real anArrowMargin = aDimensionAspect->IsText3d() + ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN + : 0.0; + + Standard_Real anArrowsWidth = (anArrowLength + anArrowMargin) * 2.0; + + theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth; + break; + } + } + + // Handle user-defined and automatic text placement + switch (theHorizontalTextPos) + { + case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break; + case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break; + case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break; + case Prs3d_DTHP_Fit: + { + gp_Vec anAttachVector (aFirstAttach, aSecondAttach); + Standard_Real aDimensionWidth = anAttachVector.Magnitude(); + Standard_Real anArrowsWidth = anArrowLength * 2.0; + Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth; + + theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; + break; + } + } + + switch (aDimensionAspect->TextVerticalPosition()) + { + case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break; + case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break; + case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break; + } +} diff --git a/src/AIS/AIS_AngleDimension.hxx b/src/AIS/AIS_AngleDimension.hxx index 31548dd8b8..13c1fc0aea 100755 --- a/src/AIS/AIS_AngleDimension.hxx +++ b/src/AIS/AIS_AngleDimension.hxx @@ -47,8 +47,8 @@ DEFINE_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension) //! as through three defined points can be built only one plane. //! Therefore, if user-defined plane differs from this one, the dimension can't be built. //! -//! In cases of two planes automatical plane by default is built on point of the -//! origin of parametrical space of the first face (the basis surface) so, that +//! In cases of two planes automatic plane by default is built on point of the +//! origin of parametric space of the first face (the basis surface) so, that //! the working plane and two faces intersection forms minimal angle between the faces. //! User can define the other point which the dimension plane should pass through //! using the appropriate constructor. This point can lay on the one of the faces or not. @@ -188,15 +188,25 @@ public: const gp_Pnt& thePoint); //! @return the display units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const; //! @return the model units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const; Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits); Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits); + //! Principle of horizontal text alignment settings: + //! - divide circle into two halves according to attachment points + //! - if aTextPos is between attach points -> Center + positive flyout + //! - if aTextPos is not between attach points but in this half -> Left or Right + positive flyout + //! - if aTextPos is between reflections of attach points -> Center + negative flyout + //! - if aTextPos is not between reflections of attach points -> Left or Right + negative flyout + Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos); + + Standard_EXPORT virtual const gp_Pnt GetTextPosition () const; + public: DEFINE_STANDARD_RTTI (AIS_AngleDimension) @@ -212,7 +222,7 @@ protected: //! @return the center of the dimension arc (the main dimension line in case of angle). Standard_EXPORT gp_Pnt GetCenterOnArc (const gp_Pnt& theFirstAttach, const gp_Pnt& theSecondAttach, - const gp_Pnt& theCenter); + const gp_Pnt& theCenter) const; //! Draws main dimension line (arc). //! @param thePresentation [in] the dimension presentation. @@ -247,6 +257,29 @@ protected: const Standard_Integer theMode, const Standard_Integer theLabelPosition); + //! Fits text alignment relatively to the dimension line; + //! it computes the value of label position and arrow orientation + //! according set in the aspect and dimension properties. + //! @param theHorizontalTextPos [in] the horizontal alignment for text position. + //! @param theLabelPosition [out] the label position, contains bits that defines + //! vertical and horizontal alignment. (for internal usage in count text position). + //! @param theIsArrowExternal [out] is the arrows external, + //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow + //! orientation automatically. + Standard_EXPORT void FitTextAlignment (const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, + Standard_Integer& theLabelPosition, + Standard_Boolean& theIsArrowsExternal) const; + + //! Adjusts aspect parameters according the text position: + //! extension size, vertical text alignment and flyout. + //! It changes flyout of the dimension. + //! @param theTextPos [in] the user defined 3d point of text position. + //! @param theExtensionSize [out] the adjusted extension size. + //! @param theAlignment [out] the horizontal label alignment. + Standard_EXPORT void AdjustParameters (const gp_Pnt& theTextPos, + Standard_Real& theExtensionSize, + Prs3d_DimensionTextHorizontalPosition& theAlignment); + protected: Standard_EXPORT virtual void ComputePlane(); diff --git a/src/AIS/AIS_DiameterDimension.cxx b/src/AIS/AIS_DiameterDimension.cxx index 761f701e72..c2679e395c 100644 --- a/src/AIS/AIS_DiameterDimension.cxx +++ b/src/AIS/AIS_DiameterDimension.cxx @@ -296,7 +296,7 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& gp_Pnt aFirstPnt (gp::Origin()); gp_Pnt aSecondPnt (gp::Origin()); - ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt); + ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt); DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt); } @@ -315,7 +315,7 @@ void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selec gp_Pnt aFirstPnt (gp::Origin()); gp_Pnt aSecondPnt (gp::Origin()); - ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt); + ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt); ComputeLinearFlyouts (theSelection, theEntityOwner, aFirstPnt, aSecondPnt); } @@ -324,15 +324,14 @@ void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selec //function : ComputeSidePoints //purpose : //======================================================================= -void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& /*theCircle*/, - const gp_Pln& /*thePlane*/, +void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& theCircle, gp_Pnt& theFirstPnt, gp_Pnt& theSecondPnt) { theFirstPnt = AnchorPoint(); - gp_Vec aRadiusVector (myCircle.Location(), theFirstPnt); - theSecondPnt = myCircle.Location().Translated (-aRadiusVector); + gp_Vec aRadiusVector (theCircle.Location(), theFirstPnt); + theSecondPnt = theCircle.Location().Translated (-aRadiusVector); } //======================================================================= @@ -358,3 +357,35 @@ Standard_Boolean AIS_DiameterDimension::IsValidAnchor (const gp_Circ& theCircle, return Abs (anAnchorDist - aRadius) > Precision::Confusion() && aCirclePlane.Contains (theAnchor, Precision::Confusion()); } + +//======================================================================= +//function : GetTextPosition +//purpose : +//======================================================================= +const gp_Pnt AIS_DiameterDimension::GetTextPosition() const +{ + if (IsTextPositionCustom()) + { + return myFixedTextPosition; + } + + // Counts text position according to the dimension parameters + return GetTextPositionForLinear (myAnchorPoint, myCircle.Location()); +} + +//======================================================================= +//function : GetTextPosition +//purpose : +//======================================================================= +void AIS_DiameterDimension::SetTextPosition (const gp_Pnt& theTextPos) +{ + if (!myIsValid) + { + return; + } + + myIsTextPositionFixed = Standard_True; + myFixedTextPosition = theTextPos; + + SetToUpdate(); +} diff --git a/src/AIS/AIS_DiameterDimension.hxx b/src/AIS/AIS_DiameterDimension.hxx index 7783f8c54c..508b15c0cb 100644 --- a/src/AIS/AIS_DiameterDimension.hxx +++ b/src/AIS/AIS_DiameterDimension.hxx @@ -114,15 +114,19 @@ public: Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Shape& theShape); //! @return the display units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const; //! @return the model units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const; Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits); Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits); + Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos); + + Standard_EXPORT virtual const gp_Pnt GetTextPosition() const; + public: DEFINE_STANDARD_RTTI(AIS_DiameterDimension) @@ -154,16 +158,14 @@ protected: protected: - //! Compute points on the circle sides for the specified dimension plane. + //! Compute points on the circle sides for the dimension plane. //! Program error exception is raised if the dimension plane "x" direction //! is orthogonal to plane (the "impossible" case). The passed dimension plane //! is the one specially computed to locate dimension presentation in circle. //! @param theCircle [in] the circle. - //! @param thePlane [in] the dimension presentation plane computed. //! @param theFirstPnt [out] the first point. //! @param theSecondPnt [out] the second point. Standard_EXPORT void ComputeSidePoints (const gp_Circ& theCircle, - const gp_Pln& thePlane, gp_Pnt& theFirstPnt, gp_Pnt& theSecondPnt); diff --git a/src/AIS/AIS_Dimension.cxx b/src/AIS/AIS_Dimension.cxx index e11b3c4580..0b549e10c5 100755 --- a/src/AIS/AIS_Dimension.cxx +++ b/src/AIS/AIS_Dimension.cxx @@ -25,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -59,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -70,7 +73,6 @@ #include #include #include -#include IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject) IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject) @@ -154,6 +156,9 @@ void AIS_Dimension::SetCustomPlane (const gp_Pln& thePlane) myPlane = thePlane; myIsPlaneCustom = Standard_True; + // Disable fixed text position + UnsetFixedTextPosition(); + // Check validity if geometry has been set already. if (myIsValid) { @@ -234,6 +239,9 @@ void AIS_Dimension::SetFlyout (const Standard_Real theFlyout) myFlyout = theFlyout; + // Disable fixed text position + UnsetFixedTextPosition(); + SetToUpdate(); } @@ -620,25 +628,8 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr Standard_ProgramError::Raise ("Can not build presentation for equal points."); } - // compute dimension line points - gp_Ax1 aPlaneNormal = GetPlane().Axis(); - gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint); - - // compute flyout direction vector - gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector; - - // create lines for layouts - gp_Lin aLine1 (theFirstPoint, aFlyoutVector); - gp_Lin aLine2 (theSecondPoint, aFlyoutVector); - - // Get flyout end points - gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); - gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); - Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); - gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint); - // For extensions we need to know arrow size, text size and extension size: get it from aspect Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length(); Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); @@ -653,28 +644,37 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr } // handle user-defined and automatic arrow placement - bool isArrowsExternal = false; - switch (aDimensionAspect->ArrowOrientation()) + Standard_Boolean isArrowsExternal = Standard_False; + Standard_Integer aLabelPosition = LabelPosition_None; + + Prs3d_DimensionTextHorizontalPosition aHorisontalTextPos = aDimensionAspect->TextHorizontalPosition(); + if (IsTextPositionCustom()) { - case Prs3d_DAO_External: isArrowsExternal = true; break; - case Prs3d_DAO_Internal: isArrowsExternal = false; break; - case Prs3d_DAO_Fit: - { - // add margin to ensure a small tail between text and arrow - Standard_Real anArrowMargin = aDimensionAspect->IsText3d() - ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN - : 0.0; + AdjustParametersForLinear (myFixedTextPosition, theFirstPoint, theSecondPoint, + anExtensionSize, aHorisontalTextPos); - Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); - Standard_Real anArrowsWidth = theIsOneSide - ? anArrowLength + anArrowMargin - : (anArrowLength + anArrowMargin) * 2.0; - - isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth; - break; - } } + FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos, + aLabelPosition, isArrowsExternal); + + // compute dimension line points + gp_Ax1 aPlaneNormal = GetPlane().Axis(); + gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint); + + // compute flyout direction vector + gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector; + + // create lines for layouts + gp_Lin aLine1 (theFirstPoint, aFlyoutVector); + gp_Lin aLine2 (theSecondPoint, aFlyoutVector); + + // Get flyout end points + gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); + gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); + + gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint); + // compute arrows positions and directions gp_Dir aFirstArrowDir = aDimensionLine.Direction().Reversed(); gp_Dir aSecondArrowDir = aDimensionLine.Direction(); @@ -703,32 +703,6 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide ? aLineEndPoint : aSecondArrowEnd; - Standard_Integer aLabelPosition = LabelPosition_None; - - // handle user-defined and automatic text placement - switch (aDimensionAspect->TextHorizontalPosition()) - { - case Prs3d_DTHP_Left : aLabelPosition |= LabelPosition_Left; break; - case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break; - case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break; - case Prs3d_DTHP_Fit: - { - Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); - Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength; - Standard_Real aContentWidth = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth; - - aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; - break; - } - } - - // handle vertical text placement options - switch (aDimensionAspect->TextVerticalPosition()) - { - case Prs3d_DTVP_Above : aLabelPosition |= LabelPosition_Above; break; - case Prs3d_DTVP_Below : aLabelPosition |= LabelPosition_Below; break; - case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break; - } switch (aLabelPosition & LabelPosition_HMask) { @@ -740,7 +714,8 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr // add label on dimension or extension line to presentation Prs3d_Root::NewGroup (thePresentation); - gp_Pnt aTextPos = (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5; + gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition + : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5; gp_Dir aTextDir = aDimensionLine.Direction(); // add text primitives @@ -831,12 +806,12 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr // add arrow extension lines to presentation Prs3d_Root::NewGroup (thePresentation); - DrawExtension (thePresentation, anExtensionSize, + DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), aFirstArrowEnd, aFirstExtensionDir, THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); if (!theIsOneSide) { - DrawExtension (thePresentation, anExtensionSize, + DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), aSecondArrowEnd, aSecondExtensionDir, THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); } @@ -900,7 +875,7 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr // add extension lines for external arrows Prs3d_Root::NewGroup (thePresentation); - DrawExtension (thePresentation, anExtensionSize, + DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), aSecondArrowEnd, aSecondExtensionDir, THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); } @@ -960,7 +935,7 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr // add extension lines for external arrows Prs3d_Root::NewGroup (thePresentation); - DrawExtension (thePresentation, anExtensionSize, + DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(), aFirstArrowEnd, aFirstExtensionDir, THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None); } @@ -1366,3 +1341,247 @@ void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt, theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin); theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin); } + +//======================================================================= +//function : GetTextPositionForLinear +//purpose : +//======================================================================= +gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const Standard_Boolean theIsOneSide) const +{ + if (!myIsValid) + { + return gp::Origin(); + } + + gp_Pnt aTextPosition (gp::Origin()); + + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + + // Get label alignment and arrow orientation. + Standard_Integer aLabelPosition = 0; + Standard_Boolean isArrowsExternal = Standard_False; + FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, + aDimensionAspect->TextHorizontalPosition(), + aLabelPosition, isArrowsExternal); + + // Compute dimension line points. + gp_Dir aPlaneNormal = GetPlane().Axis().Direction(); + gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint); + + // Compute flyout direction vector + gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir (aTargetPointsVec); + + // create lines for layouts + gp_Lin aLine1 (theFirstPoint, aFlyoutVector); + gp_Lin aLine2 (theSecondPoint, aFlyoutVector); + // Get flyout end points + gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); + gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); + + // Get text position. + switch (aLabelPosition & LabelPosition_HMask) + { + case LabelPosition_Left: + { + gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint); + Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); + + Standard_Real anOffset = isArrowsExternal + ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() + : anExtensionSize; + gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * -anOffset; + aTextPosition = aLineEndPoint.Translated (anExtensionVec); + } + break; + case LabelPosition_Right: + { + gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint); + Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize(); + + Standard_Real anOffset = isArrowsExternal + ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length() + : anExtensionSize; + gp_Vec anExtensionVec = gp_Vec (aTargetPointsDir) * anOffset; + aTextPosition = aLineBegPoint.Translated (anExtensionVec); + } + break; + case LabelPosition_HCenter: + { + aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5; + } + break; + } + + return aTextPosition; +} + +//======================================================================= +//function : AdjustAspectParameters +//purpose : +//======================================================================= +void AIS_Dimension::AdjustParametersForLinear (const gp_Pnt& theTextPos, + const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + Standard_Real& theExtensionSize, + Prs3d_DimensionTextHorizontalPosition& theAlignment) +{ + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + Standard_Real anArrowLength = aDimensionAspect->ArrowAspect()->Length(); + + //Set new automatic plane. + myPlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint); + myIsPlaneCustom = Standard_False; + + // Compute dimension line points. + gp_Dir aPlaneNormal = GetPlane().Axis().Direction(); + gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint); + gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint); + + // Compute flyout direction vector. + gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir; + + // Set flyout. + gp_Vec aFirstToTextVec (theFirstPoint, theTextPos); + + Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir); + + gp_Pnt aTextPosProj = theFirstPoint.Translated + (gp_Vec (aTargetPointsDir) * aFirstToTextVec.Magnitude() * aCos); + + // Compute flyout value and direction. + gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos); + + myFlyout = gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular()) + ? -aFlyoutVector.Magnitude() + : aFlyoutVector.Magnitude(); + + // Compute attach points (through which main dimension line passes). + gp_Pnt aFirstAttach = theFirstPoint.Translated (aFlyoutVector); + gp_Pnt aSecondAttach = theSecondPoint.Translated (aFlyoutVector); + + // Set horisontal text alignment. + if (aCos < 0.0) + { + theAlignment = Prs3d_DTHP_Left; + + Standard_Real aNewExtSize = theTextPos.Distance (aFirstAttach) - anArrowLength; + theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize; + } + else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint)) + { + theAlignment = Prs3d_DTHP_Right; + + Standard_Real aNewExtSize = theTextPos.Distance (aSecondAttach) - anArrowLength; + theExtensionSize = aNewExtSize < 0.0 ? 0.0 : aNewExtSize; + } + else + { + theAlignment = Prs3d_DTHP_Center; + } +} + +//======================================================================= +//function : FitTextAlignmentForLinear +//purpose : +//======================================================================= +void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const Standard_Boolean theIsOneSide, + const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, + Standard_Integer& theLabelPosition, + Standard_Boolean& theIsArrowsExternal) const +{ + theLabelPosition = LabelPosition_None; + theIsArrowsExternal = Standard_False; + + // Compute dimension line points + gp_Ax1 aPlaneNormal = GetPlane().Axis(); + gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint); + + // compute flyout direction vector + gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector; + + // create lines for layouts + gp_Lin aLine1 (theFirstPoint, aFlyoutVector); + gp_Lin aLine2 (theSecondPoint, aFlyoutVector); + + // Get flyout end points + gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint) + GetFlyout(), aLine1); + gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2); + + Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect(); + + gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint); + + // For extensions we need to know arrow size, text size and extension size: get it from aspect + Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length(); + + // prepare label string and compute its geometrical width + Standard_Real aLabelWidth; + TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth); + + // Add margins to cut dimension lines for 3d text + if (aDimensionAspect->IsText3d()) + { + aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0; + } + + // Handle user-defined and automatic arrow placement + switch (aDimensionAspect->ArrowOrientation()) + { + case Prs3d_DAO_External: theIsArrowsExternal = true; break; + case Prs3d_DAO_Internal: theIsArrowsExternal = false; break; + case Prs3d_DAO_Fit: + { + // Add margin to ensure a small tail between text and arrow + Standard_Real anArrowMargin = aDimensionAspect->IsText3d() + ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN + : 0.0; + + Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); + Standard_Real anArrowsWidth = theIsOneSide + ? anArrowLength + anArrowMargin + : (anArrowLength + anArrowMargin) * 2.0; + + theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth; + break; + } + } + + // Handle user-defined and automatic text placement + switch (theHorizontalTextPos) + { + case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break; + case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break; + case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break; + case Prs3d_DTHP_Fit: + { + Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint); + Standard_Real anArrowsWidth = theIsOneSide ? anArrowLength : 2.0 * anArrowLength; + Standard_Real aContentWidth = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth; + + theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter; + break; + } + } + + // Handle vertical text placement options + switch (aDimensionAspect->TextVerticalPosition()) + { + case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break; + case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break; + case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break; + } +} + +//======================================================================= +//function : UnsetFixedTextPosition +//purpose : +//======================================================================= +void AIS_Dimension::UnsetFixedTextPosition() +{ + myIsTextPositionFixed = Standard_False; + myFixedTextPosition = gp::Origin(); +} diff --git a/src/AIS/AIS_Dimension.hxx b/src/AIS/AIS_Dimension.hxx index 39e28dc4ec..1203a9bf9f 100755 --- a/src/AIS/AIS_Dimension.hxx +++ b/src/AIS/AIS_Dimension.hxx @@ -56,11 +56,11 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject) //! The specified by user units are stored in the dimension's drawer. //! //! As a drawing, the dimension is composed from the following components: -//! - Attachement (binding) points. The points where the dimension lines attaches to, for +//! - Attachment (binding) points. The points where the dimension lines attaches to, for //! length dimensions the distances are measured between these points. -//! - Main dimension line. The which extends from the attachement points in "up" direction, +//! - Main dimension line. The which extends from the attachment points in "up" direction, //! and which contains text label on it with value string. -//! - Flyouts. The lines connecting the attachement points with main dimension line. +//! - Flyouts. The lines connecting the attachment points with main dimension line. //! - Extension. The lines used to extend the main dimension line in the cases when text //! or arrows do not fit into the main dimension line due to their size. //! - Arrows. @@ -75,7 +75,7 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject) //! |flyout flyout| //! | | //! +-----------------------------------+ -//! attachement attachement +//! attachment attachment //! point point //! //! Angular dimensions: @@ -130,19 +130,46 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject) //! //! The dimension support two local selection modes: main dimension line selection and text label //! selection. These modes can be used to develop interactive modification of dimension presentations. -//! The component hilighting in these selection modes is provided by AIS_DimensionOwner class. +//! The component highlighting in these selection modes is provided by AIS_DimensionOwner class. //! Please note that selection is unavailable until the presentation is computed. //! //! The specific drawing attributes are controlled through Prs3d_DimensionAspect. The one can change //! color, arrows, text and arrow style and specify positioning of value label by setting corresponding //! values to the aspect. //! +//! Such set of parameters that consists of: +//! - flyout size and direction, +//! - user-defined dimension plane, +//! - horizontal and vertical text alignment +//! can be uniquely replaced with text position in 3d space. Therefore, there are methods to convert +//! this set of parameters to the text position and vice versa: +//! +//! - If the fixed text position is defined by user, called SetTextPosition (theTextPos) method converts +//! this 3d point to the set of parameters including adjusting of the dimension plane (this plane will be +//! automatic plane, NOT user-defined one). +//! If the fixed text position is set, the flag myIsFixedTextPosition is set to TRUE. +//! ATTENSION! myIsFixedTextPosition fixes all parameters of the set from recomputing inside +//! SetMeasureGeometry() methods. Parameters in dimension aspect (they are horizontal text position +//! and extension size) are adjusted on presentation computing step, user-defined values in +//! dimension aspect are not changed. +//! But plane and flyout as dimension position parameters are changed by SetTextPosition() method +//! according with user-defined text position. +//! If parameters from the set are changed by user with calls of setters, it leads to disabling of +//! fixed text position (myIsFixedTextPosition is set to FALSE). +//! If the fixed text position is set and geometry is changed by user (SetMeasureGeometry() method +//! is called) and the geometry doesn't satisfy computed dimension plane, the dimension is not valid. +//! +//! - If the set of parameters was set by user (may be without the user-defined plane or with it), +//! it can be converted to the text position by calling the method GetTextPosition(). In this case +//! the text position is NOT fixed, and SetMeasureGeometry() without user-defined plane adjusts +//! the automatic plane according input geometry (if it is possible). +//! class AIS_Dimension : public AIS_InteractiveObject { protected: //! Geometry type defines type of shapes on which the dimension is to be built. - //! Some type of geometry allows automatical plane computing and + //! Some type of geometry allows automatic plane computing and //! can be built without user-defined plane //! Another types can't be built without user-defined plane. enum GeometryType @@ -212,8 +239,8 @@ public: //! By default, if plane is not defined by user, it is computed automatically //! after dimension geometry is computed. //! If computed dimension geometry (points) can't be placed on the user-defined - //! plane, dimension geometry was set as unvalid (validity flag is set to false) - //! and dimension presentation wil not be computed. + //! plane, dimension geometry was set as invalid (validity flag is set to false) + //! and dimension presentation will not be computed. //! If user-defined plane allow geometry placement on it, it will be used for //! computing of the dimension presentation. //! @return dimension plane used for presentation computing. @@ -233,6 +260,22 @@ public: //! computed automatically. Standard_EXPORT void UnsetCustomPlane() { myIsPlaneCustom = Standard_False; } + //! @return TRUE if text position is set by user with method SetTextPosition(). + Standard_Boolean IsTextPositionCustom() const + { + return myIsTextPositionFixed; + } + + //! Fixes the absolute text position and adjusts flyout, plane and text alignment + //! according to it. Updates presentation if the text position is valid. + //! ATTENTION! It does not change vertical text alignment. + //! @param theTextPos [in] the point of text position. + virtual void SetTextPosition (const gp_Pnt& /*theTextPos*/) { } + + //! Computes absolute text position from dimension parameters + //! (flyout, plane and text alignment). + virtual const gp_Pnt GetTextPosition () const { return gp_Pnt(); } + public: //! Gets the dimension aspect from AIS object drawer. @@ -256,7 +299,7 @@ public: //! @return the kind of interactive. virtual AIS_KindOfInteractive Type() const { - return AIS_KOI_Relation; + return AIS_KOI_Dimension; } //! Returns true if the class of objects accepts the display mode theMode. @@ -295,6 +338,10 @@ public: Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& /*theUnits*/) { } + //! Unsets user defined text positioning and enables text positioning + //! by other parameters: text alignment, extension size, flyout and custom plane. + Standard_EXPORT void UnsetFixedTextPosition(); + public: //! Returns selection tolerance for text2d: @@ -321,7 +368,7 @@ public: Standard_EXPORT void SetFlyout (const Standard_Real theFlyout); //! Check that the input geometry for dimension is valid and the - //! presentation can be succesfully computed. + //! presentation can be successfully computed. //! @return TRUE if dimension geometry is ok. Standard_Boolean IsValid() const { @@ -426,6 +473,59 @@ protected: gp_Circ& theCircle, gp_Pnt& theMiddleArcPoint, Standard_Boolean& theIsClosed); + + //! Produce points for triangular arrow face. + //! @param thePeakPnt [in] the arrow peak position. + //! @param theDirection [in] the arrow direction. + //! @param thePlane [in] the face plane. + //! @param theArrowLength [in] the length of arrow. + //! @param theArrowAngle [in] the angle of arrow. + //! @param theSidePnt1 [out] the first side point. + //! @param theSidePnt2 [out] the second side point. + Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt, + const gp_Dir& theDirection, + const gp_Dir& thePlane, + const Standard_Real theArrowLength, + const Standard_Real theArrowAngle, + gp_Pnt& theSidePnt1, + gp_Pnt& theSidePnt2); + + //! Compute point of text position for dimension parameters + //! for linear kinds of dimensions (length, radius, diameter). + Standard_EXPORT gp_Pnt GetTextPositionForLinear (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const Standard_Boolean theIsOneSide = Standard_False) const; + + //! Fits text alignment relatively to the dimension line. + //! @param theFirstPoint [in] the first attachment point. + //! @param theSecondPoint [in] the second attachment point. + //! @param theIsOneSide [in] is the arrow displayed only on the one side of the dimension. + //! @param theHorizontalTextPos [in] the text horizontal position (alignment). + //! @param theLabelPosition [out] the label position, contains bits that defines + //! vertical and horizontal alignment. (for internal usage in count text position) + //! @param theIsArrowExternal [out] is the arrows external, + //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow + //! orientation automatically. + void FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + const Standard_Boolean theIsOneSide, + const Prs3d_DimensionTextHorizontalPosition& theHorizontalTextPos, + Standard_Integer& theLabelPosition, + Standard_Boolean& theIsArrowsExternal) const; + + //! Adjusts aspect parameters according the text position: + //! extension size, vertical text alignment and flyout. + //! It changes working plane and flyout of linear dimension. + //! @param theTextPos [in] the user defined 3d point of text position + //! @param theFirstPoint [in] the first point of linear measurement. + //! @param theSecondPoint [in] the second point of linear measurement. + //! @param theExtensionSize [out] the adjusted extension size + //! @param theAlignment [out] the horizontal label alignment. + void AdjustParametersForLinear (const gp_Pnt& theTextPos, + const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + Standard_Real& theExtensionSize, + Prs3d_DimensionTextHorizontalPosition& theAlignment); protected: //! @name Behavior to implement @@ -455,22 +555,6 @@ protected: //! @name Behavior to implement virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)&, const Handle(SelectMgr_EntityOwner)&) {} - //! Produce points for triangular arrow face. - //! @param thePeakPnt [in] the arrow peak position. - //! @param theDirection [in] the arrow direction. - //! @param thePlane [in] the face plane. - //! @param theArrowLength [in] the length of arrow. - //! @param theArrowAngle [in] the angle of arrow. - //! @param thePeakPnt [in] the arrow peak point. - //! @param theSidePnt1 [in] the first side point. - //! @param theSidePnt2 [in] the second side point. - Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt, - const gp_Dir& theDirection, - const gp_Dir& thePlane, - const Standard_Real theArrowLength, - const Standard_Real theArrowAngle, - gp_Pnt& theSidePnt1, - gp_Pnt& theSidePnt2); //! Base procedure of computing selection (based on selection geometry data). //! @param theSelection [in] the selection structure to will with primitives. @@ -525,7 +609,7 @@ protected: //! @name Selection geometry } } - //! Add new curve entry and return the referenece to populate it. + //! Add new curve entry and return the reference to populate it. Curve& NewCurve() { DimensionLine.Append( new Curve ); @@ -533,7 +617,7 @@ protected: //! @name Selection geometry return *aLastCurve; } - //! Add new arrow entry and return the referenece to populate it. + //! Add new arrow entry and return the reference to populate it. Arrow& NewArrow() { Arrows.Append( new Arrow ); @@ -550,6 +634,11 @@ protected: //! @name Value properties Standard_Real myCustomValue; //!< Value of the dimension (computed or user-defined). Standard_Boolean myIsValueCustom; //!< Is user-defined value. +protected: //! @name Fixed text position properties + + gp_Pnt myFixedTextPosition; //!< Stores text position fixed by user. + Standard_Boolean myIsTextPositionFixed; //!< Is the text label position fixed by user. + protected: //! @name Units properties Standard_ExtCharacter mySpecialSymbol; //!< Special symbol. @@ -559,10 +648,10 @@ protected: //! @name Geometrical properties GeometryType myGeometryType; //!< defines type of shapes on which the dimension is to be built. - gp_Pln myPlane; //!< Plane where dimension will be built (computed or user defined). + gp_Pln myPlane; //!< Plane where dimension will be built (computed or user defined). Standard_Boolean myIsPlaneCustom; //!< Is plane defined by user (otherwise it will be computed automatically). - Standard_Real myFlyout; //!< Flyout distance. - Standard_Boolean myIsValid; //!< Is dimension geometry properly defined. + Standard_Real myFlyout; //!< Flyout distance. + Standard_Boolean myIsValid; //!< Is dimension geometry properly defined. private: diff --git a/src/AIS/AIS_LengthDimension.cxx b/src/AIS/AIS_LengthDimension.cxx index 86b0ff47b8..1256283374 100755 --- a/src/AIS/AIS_LengthDimension.cxx +++ b/src/AIS/AIS_LengthDimension.cxx @@ -708,3 +708,35 @@ Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& th return IsValidPoints (myFirstPoint, mySecondPoint); } + +//======================================================================= +//function : GetTextPosition +//purpose : +//======================================================================= +const gp_Pnt AIS_LengthDimension::GetTextPosition() const +{ + if (IsTextPositionCustom()) + { + return myFixedTextPosition; + } + + // Counts text position according to the dimension parameters + return GetTextPositionForLinear (myFirstPoint, mySecondPoint); +} + +//======================================================================= +//function : SetTextPosition +//purpose : +//======================================================================= +void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos) +{ + if (!myIsValid) + { + return; + } + + myIsTextPositionFixed = Standard_True; + myFixedTextPosition = theTextPos; + + SetToUpdate(); +} diff --git a/src/AIS/AIS_LengthDimension.hxx b/src/AIS/AIS_LengthDimension.hxx index cd23349ab0..a9f7669129 100755 --- a/src/AIS/AIS_LengthDimension.hxx +++ b/src/AIS/AIS_LengthDimension.hxx @@ -187,15 +187,19 @@ public: const TopoDS_Shape& theSecondShape); //! @return the display units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const; - + Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const; + //! @return the model units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const; Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits); Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits); + Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos); + + Standard_EXPORT virtual const gp_Pnt GetTextPosition() const; + public: DEFINE_STANDARD_RTTI(AIS_LengthDimension) diff --git a/src/AIS/AIS_RadiusDimension.cxx b/src/AIS/AIS_RadiusDimension.cxx index ab737d099d..f6760a6080 100644 --- a/src/AIS/AIS_RadiusDimension.cxx +++ b/src/AIS/AIS_RadiusDimension.cxx @@ -262,3 +262,35 @@ Standard_Boolean AIS_RadiusDimension::IsValidAnchor (const gp_Circ& theCircle, return Abs (anAnchorDist - aRadius) > Precision::Confusion() && aCirclePlane.Contains (theAnchor, Precision::Confusion()); } + +//======================================================================= +//function : GetTextPosition +//purpose : +//======================================================================= +const gp_Pnt AIS_RadiusDimension::GetTextPosition() const +{ + if (IsTextPositionCustom()) + { + return myFixedTextPosition; + } + + // Counts text position according to the dimension parameters + return GetTextPositionForLinear (myAnchorPoint, myCircle.Location(), Standard_True); +} + +//======================================================================= +//function : GetTextPosition +//purpose : +//======================================================================= +void AIS_RadiusDimension::SetTextPosition (const gp_Pnt& theTextPos) +{ + if (!myIsValid) + { + return; + } + + myIsTextPositionFixed = Standard_True; + myFixedTextPosition = theTextPos; + + SetToUpdate(); +} diff --git a/src/AIS/AIS_RadiusDimension.hxx b/src/AIS/AIS_RadiusDimension.hxx index f501b9bd4e..c05b84b9ac 100644 --- a/src/AIS/AIS_RadiusDimension.hxx +++ b/src/AIS/AIS_RadiusDimension.hxx @@ -50,7 +50,7 @@ public: //! orientation by location of the first point on that circle. //! @param theCircle [in] the circle to measure. //! @param theAnchorPoint [in] the point to define the position - //! of the dimension attachement on the circle. + //! of the dimension attachment on the circle. Standard_EXPORT AIS_RadiusDimension (const gp_Circ& theCircle, const gp_Pnt& theAnchorPoint); @@ -88,7 +88,7 @@ public: //! Measure radius of the circle and orient the dimension so //! the dimension lines attaches to anchor point on the circle. - //! The dimension will become invalid if the radiuss of the circle + //! The dimension will become invalid if the radius of the circle //! is less than Precision::Confusion(). //! @param theCircle [in] the circle to measure. //! @param theAnchorPoint [in] the point to attach the dimension lines. @@ -102,15 +102,19 @@ public: Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Shape& theShape); //! @return the display units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const; //! @return the model units string. - Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const; + Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const; Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits); Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits); + Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos); + + Standard_EXPORT virtual const gp_Pnt GetTextPosition() const; + public: DEFINE_STANDARD_RTTI (AIS_RadiusDimension) diff --git a/src/Prs3d/Prs3d_DimensionAspect.cdl b/src/Prs3d/Prs3d_DimensionAspect.cdl index f967c4b092..e2db8a3e89 100644 --- a/src/Prs3d/Prs3d_DimensionAspect.cdl +++ b/src/Prs3d/Prs3d_DimensionAspect.cdl @@ -106,6 +106,12 @@ is ExtensionSize (me) returns Real from Standard; ---Purpose: Returns extension size. + SetArrowTailSize (me : mutable; theSize : Real from Standard); + ---Purpose: Set size for arrow tail (extension without text). + + ArrowTailSize (me) returns Real from Standard; + ---Purpose: Returns arrow tail size. + SetValueStringFormat (me : mutable; theFormat : AsciiString from TCollection); ---Purpose: Sets "sprintf"-syntax format for formatting dimension value labels. @@ -138,7 +144,10 @@ fields myExtensionSize : Real from Standard; ---Purpose: Size of arrow extensions. - -- The length of arrow tails if arrows are located outside dimension line. + -- The length of arrow tail with text if arrows are located outside dimension line. + + myArrowTailSize : Real from Standard; + ---Purpose: Size of arrow tail (extension without text). myValueStringFormat : AsciiString from TCollection; ---Purpose: "sprintf"-syntax format for formatting dimension value labels. diff --git a/src/Prs3d/Prs3d_DimensionAspect.cxx b/src/Prs3d/Prs3d_DimensionAspect.cxx index 6ab0716589..3d42ab8465 100755 --- a/src/Prs3d/Prs3d_DimensionAspect.cxx +++ b/src/Prs3d/Prs3d_DimensionAspect.cxx @@ -46,9 +46,10 @@ Prs3d_DimensionAspect::Prs3d_DimensionAspect() myArrowAspect->SetColor (Quantity_NOC_LAWNGREEN); myArrowAspect->SetAngle (M_PI * 20.0 / 180.0); myArrowAspect->SetLength (6.0); - myExtensionSize = 6.0; - myValueStringFormat = "%g"; - myToDisplayUnits = Standard_False; + myExtensionSize = 6.0; + myArrowTailSize = 6.0; + myValueStringFormat = "%g"; + myToDisplayUnits = Standard_False; } //======================================================================= @@ -261,6 +262,24 @@ Standard_Real Prs3d_DimensionAspect::ExtensionSize() const return myExtensionSize; } +//======================================================================= +//function : SetShortExtensionSize +//purpose : +//======================================================================= +void Prs3d_DimensionAspect::SetArrowTailSize (const Standard_Real theSize) +{ + myArrowTailSize = theSize; +} + +//======================================================================= +//function : ShortExtensionSize +//purpose : +//======================================================================= +Standard_Real Prs3d_DimensionAspect::ArrowTailSize() const +{ + return myArrowTailSize; +} + //======================================================================= //function : SetValueStringFormat //purpose : diff --git a/src/ViewerTest/ViewerTest_RelationCommands.cxx b/src/ViewerTest/ViewerTest_RelationCommands.cxx index d68e76e800..842ecafb9c 100644 --- a/src/ViewerTest/ViewerTest_RelationCommands.cxx +++ b/src/ViewerTest/ViewerTest_RelationCommands.cxx @@ -45,7 +45,11 @@ #include #include #include +#include #include +#include +#include +#include #include #include #include @@ -71,6 +75,9 @@ #include #include +extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName, + const Handle(AIS_InteractiveObject)& theAISObj, + Standard_Boolean theReplaceIfExists = Standard_True); extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(); extern int ViewerMainLoop(Standard_Integer argc, const char** argv); extern Handle(AIS_InteractiveContext)& TheAISContext (); @@ -83,104 +90,87 @@ extern Handle(AIS_InteractiveContext)& TheAISContext (); #define EdgeMask 0x02 #define FaceMask 0x04 -static Standard_Boolean ComputeIntersection(const gp_Lin& L,const gp_Pln& ThePl, gp_Pnt& TheInter) +//======================================================================= +//function : Get3DPointAtMousePosition +//purpose : Calculates the 3D points corresponding to the mouse position +// in the plane of the view +//======================================================================= +static gp_Pnt Get3DPointAtMousePosition() { - static IntAna_Quadric TheQuad; - TheQuad.SetQuadric(ThePl); - static IntAna_IntConicQuad QQ; - QQ.Perform(L,TheQuad); - if(QQ.IsDone()){ - if(QQ.NbPoints()>0){ - TheInter = QQ.Point(1); - return Standard_True; - } + Handle(V3d_View) aView = ViewerTest::CurrentView(); + static Select3D_Projector aProjector; + aProjector.SetView (aView); + + Standard_Real xv,yv,zv; + aView->Proj (xv,yv,zv); + Standard_Real xat,yat,zat; + aView->At(xat,yat,zat); + gp_Pln aPlane (gp_Pnt(xat,yat,zat), gp_Dir(xv,yv,zv)); + + Standard_Integer aPixX, aPixY; + Standard_Real aX, aY, aZ, aDX, aDY, aDZ; + + ViewerTest::GetMousePosition (aPixX, aPixY); + aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDX, aDY, aDZ); + gp_Lin aLine( gp_Pnt(aX, aY, aZ), gp_Dir(aDX, aDY, aDZ) ); + + // Compute intersection + Handle(Geom_Line) aGeomLine = new Geom_Line (aLine); + Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane); + GeomAPI_IntCS anIntersector (aGeomLine, aGeomPlane); + if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0) + { + return gp::Origin(); } - return Standard_False; + return anIntersector.Point (1); } //======================================================================= //function : Get3DPointAtMousePosition -//purpose : calcul du point 3D correspondant a la position souris dans le plan de -// la vue... +//purpose : Calculates the 3D points corresponding to the mouse position +// in the plane of the view //======================================================================= - -static gp_Pnt Get3DPointAtMousePosition () +static Standard_Boolean Get3DPointAtMousePosition (const gp_Pnt& theFirstPoint, + const gp_Pnt& theSecondPoint, + gp_Pnt& theOutputPoint) { - Handle(V3d_View) aview = ViewerTest::CurrentView(); - static Select3D_Projector prj; - prj.SetView(aview); - - // le plan de la vue... - Standard_Real xv,yv,zv; - aview->Proj(xv,yv,zv); - Standard_Real xat,yat,zat; - aview->At(xat,yat,zat); - gp_Pln ThePl(gp_Pnt(xat,yat,zat),gp_Dir(xv,yv,zv)); - Standard_Integer xpix,ypix; - Standard_Real x,y; - ViewerTest::GetMousePosition(xpix,ypix); - aview->Convert(xpix,ypix,x,y); // espace reel 2D de la vue... - gp_Lin L = prj.Shoot(x,y); - gp_Pnt P(0.,0.,0.); + theOutputPoint = gp::Origin(); - ComputeIntersection(L,ThePl,P); - return P; -} + Handle(V3d_View) aView = ViewerTest::CurrentView(); -//======================================================================= -//function : ComputeNewPlaneForDim -//purpose : -//======================================================================= + Standard_Integer aPixX, aPixY; + Standard_Real aX, aY, aZ, aDx, aDy, aDz, aUx, aUy, aUz; -static void ComputeNewPlaneForDim (const Handle(AIS_Relation)& R, - gp_Pln& , - gp_Pnt&) -{ -// 0 COMPOUND, -// 1 COMPSOLID, -// 2 SOLID, -// 3 SHELL, -// 4 FACE, -// 5 WIRE, -// 6 EDGE, -// 7 VERTEX, -// 8 SHAPE - TopoDS_Shape S1 = R->FirstShape(); - TopoDS_Shape S2 = R->SecondShape(); - TopAbs_ShapeEnum Typ1 = S1.ShapeType(); - TopAbs_ShapeEnum Typ2 = S2.ShapeType(); - - gp_Pnt thepoint [3]; - thepoint[0] = Get3DPointAtMousePosition(); - - // on met l'objet le plus petit en 1... - if((Standard_Integer)Typ2>(Standard_Integer)Typ1){ - - TopoDS_Shape tmpS = S1; - TopAbs_ShapeEnum tmpT = Typ1; - S1= S2; - Typ1 = Typ2; - S2= tmpS; - Typ2 = tmpT; + // Get 3D point in view coordinates and projection vector from the pixel point. + ViewerTest::GetMousePosition (aPixX, aPixY); + aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDx, aDy, aDz); + gp_Lin aProjLin (gp_Pnt(aX, aY, aZ), gp_Dir(aDx, aDy, aDz)); + + // Get plane + gp_Vec aDimVec (theFirstPoint, theSecondPoint); + aView->Up (aUx, aUy, aUz); + gp_Vec aViewUp (aUx, aUy, aUz); + + if (aDimVec.IsParallel (aViewUp, Precision::Angular())) + { + theOutputPoint = Get3DPointAtMousePosition(); + return Standard_True; } -/* - switch (Typ1){ - case TopAbs_VERTEX:{ - thepoint[0] = BRep_Tool::Pnt(S1); - if(Typ2==TopAbs_VERTEX) - thepoint[1] = BRep_Tool::Pnt(S2); - else if(Typ2==TopAbs_EDGE){ - TopoDS_Vertex Va,Vb; - TopExp::Vertices(S2,Va,Vb); - thepoint[1] = BRep_Tool::Pnt(Va); - } - else if(Typ2==TopAbs_FACE){ - } - break; + + gp_Vec aDimNormal = aDimVec ^ aViewUp; + gp_Pln aViewPlane= gce_MakePln (theFirstPoint, aDimNormal); + + // Get intersection of view plane and projection line + Handle(Geom_Plane) aPlane = new Geom_Plane (aViewPlane); + Handle(Geom_Line) aProjLine = new Geom_Line (aProjLin); + GeomAPI_IntCS anIntersector (aProjLine, aPlane); + if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0) + { + return Standard_False; } - case TopAbs_EDGE: - } -*/ + + theOutputPoint = anIntersector.Point (1); + return Standard_True; } //======================================================================= @@ -555,71 +545,70 @@ static int VDimBuilder(Draw_Interpretor& theDi, Standard_Integer theArgsNb, cons static int VAngleDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) { - Standard_Integer myCurrentIndex; - if (argc!=2) {di<<" vangledim error."<<"\n";return 1;} + Standard_Integer aCurrentIndex; + if (argc!=2) + { + di << argv[0] << " error : wrong number of parameters.\n"; + return 1; + } + TheAISContext()->CloseAllContexts(); - TheAISContext()->OpenLocalContext(); - myCurrentIndex=TheAISContext()->IndexOfCurrentLocal(); - TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) ); - di<<" Select two edges coplanar or not."<<"\n"; - Standard_Integer argcc = 5; - const char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; - const char **argvv = (const char **) buff; - while (ViewerMainLoop( argcc, argvv) ) { } - - TopoDS_Shape ShapeA; - for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) { - ShapeA = TheAISContext()->SelectedShape(); - } - // Si ShapeA est un Edge. - if (ShapeA.ShapeType()== TopAbs_EDGE ) { - - // Boucle d'attente waitpick. - Standard_Integer argccc = 5; - const char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; - const char **argvvv = (const char **) bufff; - while (ViewerMainLoop( argccc, argvvv) ) { } - // fin de la boucle - - TopoDS_Shape ShapeB; - for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) { - ShapeB = TheAISContext()->SelectedShape(); - } - // ShapeB doit etre un Edge - if (ShapeB.ShapeType()!= TopAbs_EDGE ) { - di<<" vangledim error: you shoud have selected an edge."<<"\n";return 1; - } - - // on recupere les vertexes de edgeA - TopoDS_Vertex Va,Vb; - TopExp::Vertices(TopoDS::Edge(ShapeA),Va ,Vb ); - // Recuperation des points. - gp_Pnt A=BRep_Tool::Pnt(Va); - gp_Pnt B=BRep_Tool::Pnt(Vb); - gp_Pnt C(A.X()+5 ,A.Y()+5 ,A.Z()+5 ); + aCurrentIndex = TheAISContext()->OpenLocalContext(); + // Set selection mode for edges. + TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2)); + di << "Select two edges coplanar or not.\n"; + Standard_Integer anArgsNum = 5; + const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; + const char **anArgsVec = (const char **) aBuffer; + while (ViewerMainLoop (anArgsNum, anArgsVec)) { } - // Construction du plane. Methode pas orthodoxe! - GC_MakePlane MkPlane(A ,B ,C ); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString( 90 ) ); - - // Fermeture du context local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - - // Construction de l'AIS dimension - Handle (AIS_AngleDimension) myAISDim= new AIS_AngleDimension (TopoDS::Edge(ShapeA) ,TopoDS::Edge(ShapeB)); - GetMapOfAIS().Bind (myAISDim,argv[1]); - TheAISContext()->Display(myAISDim ); - + TopoDS_Shape aFirstShape; + for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected()) + { + aFirstShape = TheAISContext()->SelectedShape(); } -else { - di<<" vangledim error: you must select 2 edges."<<"\n";return 1; -} - - + + if (aFirstShape.IsNull()) + { + di << argv[0] << " error : no picked shape.\n"; + return 1; + } + + if (aFirstShape.ShapeType()== TopAbs_EDGE) + { + while (ViewerMainLoop (anArgsNum, anArgsVec)) { } + + TopoDS_Shape aSecondShape; + for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected()) + { + aSecondShape = TheAISContext()->SelectedShape(); + } + + if (aSecondShape.IsNull()) + { + di << argv[0] << " error : no picked shape.\n"; + return 1; + } + + if (aSecondShape.ShapeType() != TopAbs_EDGE) + { + di << argv[0] <<" error: you should have selected an edge.\n"; return 1; + } + + // Close local context to draw dimension in the neutral point. + TheAISContext()->CloseLocalContext (aCurrentIndex); + + // Construct the dimension. + Handle (AIS_AngleDimension) aDim= new AIS_AngleDimension (TopoDS::Edge(aFirstShape) ,TopoDS::Edge(aSecondShape)); + VDisplayAISObject (argv[1], aDim); + } + else + { + di << argv[0] << " error: you must select 2 edges.\n"; + return 1; + } + return 0; } @@ -632,59 +621,69 @@ else { static int VDiameterDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) { // Declarations - Standard_Integer myCurrentIndex; - Standard_Real theRadius; - + Standard_Integer aCurrentIndex; + Standard_Real aRadius; + // Verification - if (argc!=2) {di<<" vdiameterdim error"<<"\n";return 1;} - // Fermeture des contextes locaux + if (argc != 2) + { + di<<" vdiameterdim error"<<"\n"; + return 1; + } + + // Close all local contexts TheAISContext()->CloseAllContexts(); - // Ouverture d'un contexte local et recuperation de son index. + // Open local context and get its index for recovery TheAISContext()->OpenLocalContext(); - myCurrentIndex=TheAISContext()->IndexOfCurrentLocal(); + aCurrentIndex = TheAISContext()->IndexOfCurrentLocal(); - // On active les modes de selections Edges et Faces. + // Activate 'edge' selection mode TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) ); di<<" Select an circled edge."<<"\n"; - // Boucle d'attente waitpick. + // Loop that will handle the picking. Standard_Integer argcc = 5; const char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; const char **argvv = (const char **) buff; while (ViewerMainLoop( argcc, argvv) ) { } - // fin de la boucle + // end of the loop. - TopoDS_Shape ShapeA; - for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) { - ShapeA = TheAISContext()->SelectedShape(); + TopoDS_Shape aShape; + for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected()) + { + aShape = TheAISContext()->SelectedShape(); } - if (ShapeA.ShapeType()==TopAbs_EDGE ) { - - // Recuperation du rayon - BRepAdaptor_Curve theCurve(TopoDS::Edge(ShapeA)); - if (theCurve.GetType()!=GeomAbs_Circle ) {di<<"vdiameterdim error: the edge is not a circular one."<<"\n";return 1;} - else { - gp_Circ theGpCircle=theCurve.Circle(); - theRadius=2.*theGpCircle.Radius(); - } - - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theRadius ) ); - // Construction de L'AIS_AngleDimension. - TheAISContext()->CloseLocalContext(myCurrentIndex); - - Handle (AIS_DiameterDimension) myDiamDim= new AIS_DiameterDimension(ShapeA); - GetMapOfAIS().Bind (myDiamDim,argv[1]); - TheAISContext()->Display(myDiamDim ); - + + if (aShape.IsNull()) + { + di << argv[0] << ": no shape is selected." << "\n"; + return 1; } - - else { - di<<" vdiameterdim error: the selection of a face or an edge was expected."<<"\n";return 1; + + if (aShape.ShapeType() != TopAbs_EDGE) + { + di << " vdiameterdim error: the selection of a face or an edge was expected." << "\n"; + return 1; } - + + // Compute the radius + BRepAdaptor_Curve aCurve (TopoDS::Edge (aShape)); + + if (aCurve.GetType() != GeomAbs_Circle) + { + di << "vdiameterdim error: the edge is not a circular one." << "\n"; + return 1; + } + + gp_Circ aCircle = aCurve.Circle(); + aRadius = 2.0 * aCircle.Radius(); + + // Construction of the diameter dimension. + TheAISContext()->CloseLocalContext (aCurrentIndex); + Handle (AIS_DiameterDimension) aDiamDim= new AIS_DiameterDimension (aShape); + VDisplayAISObject (argv[1], aDiamDim); + return 0; - } @@ -1246,339 +1245,292 @@ static int VIdenticRelation(Draw_Interpretor& di, Standard_Integer argc, const c #include #include #include -#include +#include #include #include + static int VLenghtDimension(Draw_Interpretor& di, Standard_Integer argc, const char** argv) { // Declarations - Standard_Integer myCurrentIndex; - Standard_Real theDist; - + Standard_Integer aCurrentIndex; // Verification - if (argc!=2) {di<<" videntity error: no arguments allowed."<<"\n";return 1;} - - // Fermeture des contextes locaux + if (argc != 2) + { + di << argv[0] << " error: wrong number of arguments.\n"; + return 1; + } + + // Close all local contexts TheAISContext()->CloseAllContexts(); - - // Ouverture d'un contexte local et recuperation de son index. - myCurrentIndex = TheAISContext()->OpenLocalContext(); - TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) ); - TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) ); - TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) ); - di<<" Select an edge, a face or a vertex. "<<"\n"; - - // Boucle d'attente waitpick. + + // Open local context + aCurrentIndex = TheAISContext()->OpenLocalContext(); + // Activate 'edge', 'face' and 'vertex' selection modes. + TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2)); + TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1)); + TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4)); + + // First shape picking + di << " Select an edge, a face or a vertex. " << "\n"; + // Loop that will handle the picking. Standard_Integer argc1 = 5; const char *buf1[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; const char **argv1 = (const char **) buf1; while (ViewerMainLoop( argc1, argv1) ) { } + // end of the loop. - // fin de la boucle - TopoDS_Shape ShapeA; - for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) { - ShapeA = TheAISContext()->SelectedShape(); + TopoDS_Shape aFirstShape; + for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected()) + { + aFirstShape = TheAISContext()->SelectedShape(); } - di<<" Select an edge, a face or a vertex. "<<"\n"; - // Boucle d'attente waitpick. + + if (aFirstShape.IsNull()) + { + di << argv[0] << "error: no first picked shape.\n"; + return 1; + } + + // Second shape picking + di << " Select an edge, a face or a vertex. " << "\n"; + // Loop that will handle the picking. Standard_Integer argc2 = 5; const char *buf2[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; const char **argv2 = (const char **) buf2; while (ViewerMainLoop( argc2, argv2) ) { } - // fin de la boucle - - TopoDS_Shape ShapeB; - for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) { - ShapeB = TheAISContext()->SelectedShape(); + + TopoDS_Shape aSecondShape; + for(TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected()) + { + aSecondShape = TheAISContext()->SelectedShape(); } - // ShapeA est un edge. - // =================== - if (ShapeA.ShapeType()==TopAbs_EDGE ) { - TopoDS_Edge EdgeA=TopoDS::Edge(ShapeA); - - // Si ShapeB est un edge - if (ShapeB.ShapeType()==TopAbs_EDGE ) { - TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB); - BRepExtrema_ExtCC myDeltaEdge (EdgeA ,EdgeB ); - // on verifie qu'ils ne sont pas paralleles. - if (!myDeltaEdge.IsParallel() ) {di<<"vlenghtdim error: non parallel edges."<<"\n";return 1; } - - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt(myDeltaEdge.SquareDistance(1))*10. )/10.; - - // On recupere 3 Points des edges pour construire un plane. - TopoDS_Vertex Va,Vb,Vc,Vd; - TopExp::Vertices(EdgeA,Va,Vb); - TopExp::Vertices(EdgeB,Vc,Vd); - gp_Pnt A=BRep_Tool::Pnt(Va); - gp_Pnt B=BRep_Tool::Pnt(Vb); - gp_Pnt C=BRep_Tool::Pnt(Vc); - - // Creation du Plane contenant la relation. - GC_MakePlane MkPlane(A,B,C); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // On ferme le contexte local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (EdgeA,EdgeB,theGeomPlane->Pln()); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); + + if (aSecondShape.IsNull()) + { + di << argv[0] << "error: no second picked shape.\n"; + return 1; + } + + if (aFirstShape.ShapeType() == TopAbs_EDGE) + { + TopoDS_Edge EdgeA = TopoDS::Edge (aFirstShape); + + if (aSecondShape.ShapeType() == TopAbs_EDGE) + { + TopoDS_Edge EdgeB = TopoDS::Edge (aSecondShape); + BRepExtrema_ExtCC myDeltaEdge (EdgeA ,EdgeB); + + if (!myDeltaEdge.IsParallel()) + { + di << argv[0] << " error: non parallel edges." << "\n"; + return 1; + } + + // 3 points of edges is recovered to build a plane + TopoDS_Vertex aVertex1, aVertex2, aVertex3, aVertex4; + TopExp::Vertices (EdgeA, aVertex1, aVertex2); + TopExp::Vertices (EdgeB, aVertex3, aVertex4); + gp_Pnt A = BRep_Tool::Pnt (aVertex1); + gp_Pnt B = BRep_Tool::Pnt (aVertex2); + gp_Pnt C = BRep_Tool::Pnt (aVertex3); + + gce_MakePln aMakePlane (A,B,C); + gp_Pln aPlane= aMakePlane.Value(); + + // Close local context + TheAISContext()->CloseLocalContext (aCurrentIndex); + + // Construct the dimension + Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (EdgeA, EdgeB, aPlane); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); } - - // Si ShapeB est un vertex. - else if (ShapeB.ShapeType()==TopAbs_VERTEX ) { - - TopoDS_Vertex VertexB=TopoDS::Vertex(ShapeB); - BRepExtrema_ExtPC myDeltaEdgeVertex (VertexB ,EdgeA ); - - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt (myDeltaEdgeVertex.SquareDistance(1))*10. )/10.; - - // On recupere 2 Points de EdgeA pour construire un plane. - TopoDS_Vertex Va,Vb; - TopExp::Vertices(EdgeA,Va,Vb); - gp_Pnt A=BRep_Tool::Pnt(Va); - gp_Pnt B=BRep_Tool::Pnt(Vb); - gp_Pnt C=BRep_Tool::Pnt(VertexB); - - GC_MakePlane MkPlane(A,B,C); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - TheAISContext()->CloseLocalContext(myCurrentIndex); - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (EdgeA,VertexB,theGeomPlane->Pln()); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - - + + else if (aSecondShape.ShapeType() == TopAbs_VERTEX) + { + TopoDS_Vertex aVertex = TopoDS::Vertex (aSecondShape); + BRepExtrema_ExtPC myDeltaEdgeVertex (aVertex ,EdgeA); + + TopoDS_Vertex aVertex1, aVertex2; + TopExp::Vertices (EdgeA, aVertex1, aVertex2); + gp_Pnt A=BRep_Tool::Pnt (aVertex1); + gp_Pnt B=BRep_Tool::Pnt (aVertex2); + gp_Pnt C=BRep_Tool::Pnt (aVertex); + + gce_MakePln aMakePlane (A,B,C); + gp_Pln aPlane= aMakePlane.Value(); + + TheAISContext()->CloseLocalContext (aCurrentIndex); + Handle(AIS_LengthDimension) aLenghtDim=new AIS_LengthDimension (EdgeA, aVertex, aPlane); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); } - - // Si ShapeB est une Face + + // Second shape is a face else { - TopoDS_Face FaceB=TopoDS::Face(ShapeB); - BRepExtrema_ExtCF myDeltaEdgeFace (EdgeA,FaceB ); - // On verifie que l'edge est bien parallele a la face. - if (!myDeltaEdgeFace.IsParallel() ) {di<<"vdistdim error: the edge isn't parallel to the face;can't compute the distance. "<<"\n";return 1; } + TopoDS_Face FaceB = TopoDS::Face (aSecondShape); + BRepExtrema_ExtCF aDeltaEdgeFace (EdgeA,FaceB); - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (FaceB,EdgeA); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); + if (!aDeltaEdgeFace.IsParallel()) + { + di << argv[0] << "error: the edge isn't parallel to the face;can't compute the distance." << "\n"; + return 1; + } + + Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceB, EdgeA); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); + } + } + else if (aFirstShape.ShapeType() == TopAbs_VERTEX) + { + TopoDS_Vertex VertexA = TopoDS::Vertex (aFirstShape); + if (aSecondShape.ShapeType() == TopAbs_EDGE ) + { + TopoDS_Edge EdgeB=TopoDS::Edge (aSecondShape); + BRepExtrema_ExtPC aDeltaEdgeVertex (VertexA, EdgeB); + + TopoDS_Vertex aVertex1, aVertex2; + TopExp::Vertices(EdgeB, aVertex1, aVertex2); + gp_Pnt A = BRep_Tool::Pnt (aVertex1); + gp_Pnt B = BRep_Tool::Pnt (aVertex2); + gp_Pnt C = BRep_Tool::Pnt (VertexA); + + gce_MakePln aMakePlane (A,B,C); + gp_Pln aPlane = aMakePlane.Value(); + + // Close local contex by its index. + TheAISContext()->CloseLocalContext (aCurrentIndex); + + // Construct the dimension. + Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (EdgeB,VertexA, aPlane); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); + } + + else if (aSecondShape.ShapeType() == TopAbs_VERTEX) + { + TopoDS_Vertex VertexB = TopoDS::Vertex (aSecondShape); + + gp_Pnt A = BRep_Tool::Pnt (VertexA); + gp_Pnt B = BRep_Tool::Pnt (VertexB); + gp_Pnt C(B.X() + 10.0, B.Y() + 10.0, B.Z() + 10.0); + + gce_MakePln aMakePlane (A,B,C); + gp_Pln aPlane= aMakePlane.Value(); + + TheAISContext()->CloseLocalContext (aCurrentIndex); + + Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (VertexA, VertexB, aPlane); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); + } + // The second shape is face + else + { + TopoDS_Face FaceB = TopoDS::Face (aSecondShape); + + BRepExtrema_ExtPF aDeltaVertexFace (VertexA, FaceB); + + gp_Pnt A = BRep_Tool::Pnt (VertexA); + + // Recover edge from face. + TopExp_Explorer aFaceExp (FaceB,TopAbs_EDGE); + TopoDS_Edge aSecondEdge = TopoDS::Edge (aFaceExp.Current()); + + TopoDS_Vertex aVertex1, aVertex2; + TopExp::Vertices (aSecondEdge, aVertex1, aVertex2); + gp_Pnt C = BRep_Tool::Pnt (aVertex2); + + gp_Pnt aProjA = aDeltaVertexFace.Point(1); + BRepBuilderAPI_MakeVertex aVertexMaker (aProjA); + TopoDS_Vertex aVertexAProj = aVertexMaker.Vertex(); + + // Create working plane for the dimension. + gce_MakePln aMakePlane (A, aProjA, C); + gp_Pln aPlane = aMakePlane.Value(); + + TheAISContext()->CloseLocalContext (aCurrentIndex); + + // Construct the dimension. + Handle(AIS_LengthDimension ) aLenghtDim = new AIS_LengthDimension (VertexA, aVertexAProj, aPlane); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); } } - // ShapeA est un vertex - // ==================== - if (ShapeA.ShapeType()==TopAbs_VERTEX ) { - TopoDS_Vertex VertexA=TopoDS::Vertex(ShapeA); - - // Si ShapeB est un edge. - if (ShapeB.ShapeType()==TopAbs_EDGE ) { - TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB); - BRepExtrema_ExtPC myDeltaEdgeVertex (VertexA ,EdgeB ); - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt (myDeltaEdgeVertex.SquareDistance(1))*10. )/10.; - - // On recupere 2 Points de EdgeB pour construire un plane. - TopoDS_Vertex Va,Vb; - TopExp::Vertices(EdgeB,Va,Vb); - gp_Pnt A=BRep_Tool::Pnt(Va); - gp_Pnt B=BRep_Tool::Pnt(Vb); - gp_Pnt C=BRep_Tool::Pnt(VertexA); - - // Creation du Plane contenant la relation. - GC_MakePlane MkPlane(A,B,C); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - // Fermeture du contexte local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (EdgeB,VertexA,theGeomPlane->Pln()); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - - } - - // Si ShapeB est un vertex. - else if (ShapeB.ShapeType()==TopAbs_VERTEX ) { - TopoDS_Vertex VertexB=TopoDS::Vertex(ShapeB); - BRepExtrema_DistShapeShape myDeltaVertexVertex (VertexA ,VertexB ); - // On saisit la distance et on l'arrondit! - theDist=Round (myDeltaVertexVertex.Value()*10. )/10.; - - // Les deux premiers points. - gp_Pnt A=BRep_Tool::Pnt(VertexA); - gp_Pnt B=BRep_Tool::Pnt(VertexB); - gp_Pnt C(B.X()+10,B.Y()+10,B.Z()+10); + // The first shape is a face. + else + { + TopoDS_Face FaceA = TopoDS::Face (aFirstShape); - GC_MakePlane MkPlane(A,B,C); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - // Fermeture du contexte local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (VertexA,VertexB,theGeomPlane->Pln()); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - - - - + if (aSecondShape.ShapeType() == TopAbs_EDGE) + { + TopoDS_Edge EdgeB = TopoDS::Edge (aSecondShape); + BRepExtrema_ExtCF aDeltaEdgeFace (EdgeB,FaceA ); + + if (!aDeltaEdgeFace.IsParallel()) + { + di << argv[0] << " error: the edge isn't parallel to the face;can't compute the distance. " << "\n"; + return 1; + } + + Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceA, EdgeB); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); } - - // Si ShapeB est une Face - else { - - TopoDS_Face FaceB=TopoDS::Face(ShapeB); - BRepExtrema_ExtPF myDeltaVertexFace (VertexA ,FaceB ); - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt (myDeltaVertexFace.SquareDistance(1))*10. )/10.; - - // Premier point. - gp_Pnt A=BRep_Tool::Pnt(VertexA); - - // On recupere 1 edge de FaceB. - TopExp_Explorer FaceExp(FaceB,TopAbs_EDGE); - TopoDS_Edge EdFromB=TopoDS::Edge(FaceExp.Current() ); - // On recupere les deux vertexes extremites de l'edge de face B - TopoDS_Vertex Vb,Vc; - TopExp::Vertices(EdFromB,Vb,Vc); - gp_Pnt C=BRep_Tool::Pnt(Vc); - - // On projette le point B sur la Face car il - // n'existe pas de constructeurs AIS_LD PointFace - // on est donc oblige de creer un nouveau TopoDS_Vertex. - gp_Pnt theProjA=myDeltaVertexFace.Point(1); - BRepBuilderAPI_MakeVertex theVertexMaker(theProjA); - TopoDS_Vertex VertexAproj=theVertexMaker.Vertex(); - // Creation du Plane contenant la relation. - GC_MakePlane MkPlane(A,theProjA,C); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - // Fermeture du contexte local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (VertexA,VertexAproj,theGeomPlane->Pln()); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - - } - - - - } - - // ShapeA est une Face - // =================== - else { - TopoDS_Face FaceA=TopoDS::Face(ShapeA); - // Si ShapeB est un edge. - if (ShapeB.ShapeType()==TopAbs_EDGE ) { - TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB); - BRepExtrema_ExtCF myDeltaEdgeFace (EdgeB,FaceA ); - // On verifie que l'edge est bien parallele a la face. - if (!myDeltaEdgeFace.IsParallel() ) {di<<"vdistdim error: the edge isn't parallel to the face;can't compute the distance. "<<"\n";return 1; } - - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt (myDeltaEdgeFace.SquareDistance(1))*10. )/10.; - - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (FaceA,EdgeB); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - - } - - // Si ShapeB est un vertex. - else if (ShapeB.ShapeType()==TopAbs_VERTEX ) { - - TopoDS_Vertex VertexB=TopoDS::Vertex(ShapeB); - BRepExtrema_ExtPF myDeltaVertexFace (VertexB ,FaceA ); - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt (myDeltaVertexFace.SquareDistance(1))*10. )/10.; - - // Premier point. - gp_Pnt B=BRep_Tool::Pnt(VertexB); - - // On recupere 1 edge de FaceA. - TopExp_Explorer FaceExp(FaceA,TopAbs_EDGE); - TopoDS_Edge EdFromA=TopoDS::Edge(FaceExp.Current() ); - // On recupere les deux vertexes extremites de l'edge de face A - TopoDS_Vertex Va,Vc; - TopExp::Vertices(EdFromA,Va,Vc); - gp_Pnt A=BRep_Tool::Pnt(Va); + + else if (aSecondShape.ShapeType() == TopAbs_VERTEX) + { + TopoDS_Vertex VertexB = TopoDS::Vertex (aSecondShape); + BRepExtrema_ExtPF aDeltaVertexFace (VertexB, FaceA); + + gp_Pnt B = BRep_Tool::Pnt (VertexB); + + TopExp_Explorer aFaceExp (FaceA, TopAbs_EDGE); + TopoDS_Edge anEdgeFromA = TopoDS::Edge (aFaceExp.Current()); + TopoDS_Vertex aVertex1, aVertex2; + TopExp::Vertices(anEdgeFromA, aVertex1, aVertex2); + gp_Pnt A=BRep_Tool::Pnt(aVertex1); #ifdef DEB - gp_Pnt C = BRep_Tool::Pnt(Vc); + gp_Pnt C = BRep_Tool::Pnt(aVertex2); #endif - // On projette le point B sur la Face car il - // n'existe pas de constructeurs AIS_LD PointFace - // on est donc oblige de creer un nouveau TopoDS_Vertex. - gp_Pnt theProjB=myDeltaVertexFace.Point(1); - BRepBuilderAPI_MakeVertex theVertexMaker(theProjB); - TopoDS_Vertex VertexBproj=theVertexMaker.Vertex(); - // Creation du Plane contenant la relation. - GC_MakePlane MkPlane(A,B,theProjB); - Handle(Geom_Plane) theGeomPlane=MkPlane.Value(); - - // Fermeture du contexte local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // on construit l'AISLenghtDimension mais en utilisant le constructeur Vertex Vertex. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (VertexB,VertexBproj,theGeomPlane->Pln()); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - + gp_Pnt aProjB = aDeltaVertexFace.Point(1); + BRepBuilderAPI_MakeVertex aVertexMaker (aProjB); + TopoDS_Vertex aVertexBProj = aVertexMaker.Vertex(); + gce_MakePln aMakePlane (A, B, aProjB); + gp_Pln aPlane= aMakePlane.Value(); + + TheAISContext()->CloseLocalContext(aCurrentIndex); + + Handle(AIS_LengthDimension) aLenghtDim =new AIS_LengthDimension (VertexB, aVertexBProj, aPlane); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); } - - // Si ShapeB est une Face - else { - - TopoDS_Face FaceB=TopoDS::Face(ShapeB); - BRepExtrema_ExtFF myDeltaFaceFace (FaceA ,FaceB ); - // On verifie que les deux faces sont bien parelles. - if (!myDeltaFaceFace.IsParallel() ) {di<<"vdistdim error: the faces are not parallel. "<<"\n";return 1; } - - // On saisit la distance et on l'arrondit! - theDist=Round (sqrt (myDeltaFaceFace.SquareDistance(1))*10. )/10.; - // Fermeture du contexte local. - TheAISContext()->CloseLocalContext(myCurrentIndex); - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("d=")+TCollection_ExtendedString(theDist ) ); - - // on construit l'AISLenghtDimension. - Handle(AIS_LengthDimension ) myLenghtDim=new AIS_LengthDimension (FaceA,FaceB); - TheAISContext()->Display(myLenghtDim ); - GetMapOfAIS().Bind (myLenghtDim ,argv[1]); - + // the second shape is face. + else + { + TopoDS_Face FaceB = TopoDS::Face (aSecondShape); + BRepExtrema_ExtFF aDeltaFaceFace (FaceA, FaceB); + + if (!aDeltaFaceFace.IsParallel()) + { + di << argv[0] << " error: the faces are not parallel. "<<"\n"; + return 1; + } + + TheAISContext()->CloseLocalContext (aCurrentIndex); + + Handle(AIS_LengthDimension) aLenghtDim = new AIS_LengthDimension (FaceA,FaceB); + TheAISContext()->Display (aLenghtDim); + GetMapOfAIS().Bind (aLenghtDim, argv[1]); } - } - - - + return 0; - } @@ -1596,103 +1548,88 @@ static int VLenghtDimension(Draw_Interpretor& di, Standard_Integer argc, const c static int VRadiusDimBuilder(Draw_Interpretor& di, Standard_Integer argc, const char** argv) { // Declarations - Standard_Integer myCurrentIndex; - Standard_Real theRadius; - + Standard_Integer aCurrentIndex; + Standard_Real aRadius; + TopoDS_Edge anEdge; // Verification - if (argc!=2) {di<<" vradiusdim error"<<"\n";return 1;} - - // Fermeture des contextes locaux + if (argc != 2) + { + di << argv[0] << " error: wrong number of parameters." << "\n"; + return 1; + } + + // Close all local contexts TheAISContext()->CloseAllContexts(); - - // Ouverture d'un contexte local et recuperation de son index. + + // Open local context and get its index for recovery. TheAISContext()->OpenLocalContext(); - myCurrentIndex=TheAISContext()->IndexOfCurrentLocal(); - - // On active les modes de selections Edges et Faces. - TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) ); - TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) ); - di<<" Select an circled edge or face."<<"\n"; - - // Boucle d'attente waitpick. + aCurrentIndex = TheAISContext()->IndexOfCurrentLocal(); + + // Current selection modes - faces and edges + TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2)); + TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4)); + di << " Select a circled edge or face." << "\n"; + + // Loop that will be handle picking. Standard_Integer argcc = 5; const char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; const char **argvv = (const char **) buff; - while (ViewerMainLoop( argcc, argvv) ) { } - // fin de la boucle - - TopoDS_Shape ShapeA; - for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) { - ShapeA = TheAISContext()->SelectedShape(); + while (ViewerMainLoop (argcc, argvv)) { } + // end of the loop + + TopoDS_Shape aShape; + + for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected() ) + { + aShape = TheAISContext()->SelectedShape(); } - - // Shape A est un edge. - if (ShapeA.ShapeType()==TopAbs_EDGE ) { - - TopoDS_Edge EdgeA=TopoDS::Edge(ShapeA); - // Recuperation du rayon - BRepAdaptor_Curve theCurve(TopoDS::Edge(ShapeA)); - if (theCurve.GetType()!=GeomAbs_Circle ) {di<<"vradiusdim error: the edge is not a circular one."<<"\n";return 1;} - else { - gp_Circ theGpCircle=theCurve.Circle(); - theRadius=theGpCircle.Radius(); - // On arrondit le rayon - theRadius=Round (theRadius*10. )/10.; - } - - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("r=")+TCollection_ExtendedString(theRadius ) ); - - // Fermeture du contexte. - TheAISContext()->CloseLocalContext(myCurrentIndex); - - // Construction de L'AIS_RadiusDimension. - Handle (AIS_RadiusDimension) myRadDim= new AIS_RadiusDimension(ShapeA); - GetMapOfAIS().Bind (myRadDim,argv[1]); - TheAISContext()->Display(myRadDim ); - - + + if (aShape.IsNull()) + { + di << argv[0] << ": no shape is selected." << "\n"; + return 1; } - - // Shape A est une face - else if (ShapeA.ShapeType()==TopAbs_FACE ) { - - // on recupere un edge de la face. - TopoDS_Face FaceA=TopoDS::Face(ShapeA); - // on explore. - TopExp_Explorer FaceExp(FaceA,TopAbs_EDGE); - TopoDS_Edge EdgeFromA=TopoDS::Edge(FaceExp.Current() ); - - // Recuperation du rayon - BRepAdaptor_Curve theCurve(EdgeFromA ); - if (theCurve.GetType()!=GeomAbs_Circle ) {di<<"vradiusdim error: the face is not a circular one."<<"\n";return 1;} - else { - gp_Circ theGpCircle=theCurve.Circle(); - theRadius=theGpCircle.Radius(); - // On arrondit le rayon - theRadius=Round (theRadius*10. )/10.; - } - - // Construction du texte. - TCollection_ExtendedString TheMessage_Str(TCollection_ExtendedString("r=")+TCollection_ExtendedString(theRadius ) ); - - // Fermeture du contexte. - TheAISContext()->CloseLocalContext(myCurrentIndex); - - // Construction de L'AIS_RadiusDimension. - Handle (AIS_RadiusDimension) myRadDim= new AIS_RadiusDimension(ShapeA); - GetMapOfAIS().Bind (myRadDim,argv[1]); - TheAISContext()->Display(myRadDim ); - - + + if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_FACE) + { + di << argv[0] << " error: the selection of a face or an edge was expected." << "\n"; + return 1; } - - else { - di<<" vradiusdim error: the selection of a face or an edge was expected."<<"\n";return 1; + + if (aShape.ShapeType() == TopAbs_EDGE) + { + anEdge = TopoDS::Edge (aShape); } - + else // Face + { + // Recover an edge of the face. + TopoDS_Face aFace = TopoDS::Face (aShape); + + TopExp_Explorer aFaceExp (aFace,TopAbs_EDGE); + anEdge = TopoDS::Edge (aFaceExp.Current()); + } + + // Compute the radius + BRepAdaptor_Curve aCurve (anEdge); + if (aCurve.GetType() != GeomAbs_Circle) + { + di << argv[0] << " error: the edge is not a circular one." << "\n"; + return 1; + } + else + { + gp_Circ aCircle = aCurve.Circle(); + aRadius = aCircle.Radius(); + aRadius = Round (aRadius * 10.0) / 10.0; + } + // Close the context + TheAISContext()->CloseLocalContext (aCurrentIndex); + + // Construct radius dimension + Handle (AIS_RadiusDimension) aRadDim= new AIS_RadiusDimension (aShape); + VDisplayAISObject (argv[1], aRadDim); + return 0; - } @@ -2398,94 +2335,346 @@ static int VSymmetricBuilder(Draw_Interpretor& di, Standard_Integer argc, const return 0; } + +//======================================================================= +//function : VDimParam +//purpose : Moves dimension or relation text label to defined or picked +// position and updates the object. +//======================================================================= +static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec) +{ + if (theArgNum < 3) + { + theDi << theArgVec[0] << " error: the wrong number of input parameters.\n"; + return 1; + } + + // Get dimension name + TCollection_AsciiString aName (theArgVec[1]); + if (!GetMapOfAIS().IsBound2 (aName)) + { + theDi << theArgVec[0] << "error: no object with this name.\n"; + return 1; + } + + Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2 (aName)); + if (anObject->Type() != AIS_KOI_Dimension) + { + theDi << theArgVec[0] << "error: no dimension with this name.\n"; + return 1; + } + Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (anObject); + Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect(); + + // Parse parameters + gp_Pln aWorkingPlane; + Standard_Real aCustomFlyout = 0.0; + + for (Standard_Integer anIt = 2; anIt < theArgNum; ++anIt) + { + TCollection_AsciiString anArgString = theArgVec[anIt]; + TCollection_AsciiString aParamName; + TCollection_AsciiString aParamValue; + if (ViewerTest::SplitParameter (anArgString, aParamName, aParamValue)) + { + aParamName.LowerCase(); + aParamValue.LowerCase(); + + if (aParamName == "text") + { + anAspect->MakeText3d (aParamValue == "3d"); + } + else if (aParamName == "name") + { + if (aParamValue.IsEmpty()) + { + std::cerr << theArgVec[0] << ": no name for dimension.\n"; + return 1; + } + + aName = aParamValue; + } + else if (aParamName == "plane") + { + if (aParamValue == "xoy") + { + aWorkingPlane = gp_Pln (gp_Ax3 (gp::XOY())); + } + else if (aParamValue == "zox") + { + aWorkingPlane = gp_Pln (gp_Ax3 (gp::ZOX())); + } + else if (aParamValue == "yoz") + { + aWorkingPlane = gp_Pln (gp_Ax3 (gp::YOZ())); + } + else + { + std::cerr << theArgVec[0] << ": wrong plane.\n"; + return 1; + } + } + else if (aParamName == "label") + { + NCollection_List aListOfLabelVals; + while (aParamValue.Length() > 0) + { + TCollection_AsciiString aValue = aParamValue; + + Standard_Integer aSeparatorPos = aParamValue.Search (","); + if (aSeparatorPos >= 0) + { + aValue.Trunc (aSeparatorPos - 1); + aParamValue.Remove (aSeparatorPos, 1); + } + + aListOfLabelVals.Append (aValue); + + aParamValue.Remove (1, aValue.Length()); + } + + NCollection_List::Iterator aLabelValueIt (aListOfLabelVals); + for ( ; aLabelValueIt.More(); aLabelValueIt.Next()) + { + aParamValue = aLabelValueIt.Value(); + + if (aParamValue == "left") + { + anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left); + } + else if (aParamValue == "right") + { + anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right); + } + else if (aParamValue == "hcenter") + { + anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center); + } + else if (aParamValue == "hfit") + { + anAspect->SetTextHorizontalPosition (Prs3d_DTHP_Fit); + } + else if (aParamValue == "above") + { + anAspect->SetTextVerticalPosition (Prs3d_DTVP_Above); + } + else if (aParamValue == "below") + { + anAspect->SetTextVerticalPosition (Prs3d_DTVP_Below); + } + else if (aParamValue == "vcenter") + { + anAspect->SetTextVerticalPosition (Prs3d_DTVP_Center); + } + else + { + std::cerr << theArgVec[0] << ": invalid label position: \"" << aParamValue << "\".\n"; + return 1; + } + } + } + else if (aParamName == "flyout") + { + if (!aParamValue.IsRealValue()) + { + std::cerr << theArgVec[0] << ": numeric value expected for flyout.\n"; + return 1; + } + + aCustomFlyout = aParamValue.RealValue(); + aDim->SetFlyout (aCustomFlyout); + } + else if (aParamName == "arrows") + { + if (aParamValue == "external") + { + anAspect->SetArrowOrientation (Prs3d_DAO_External); + } + else if (aParamValue == "internal") + { + anAspect->SetArrowOrientation (Prs3d_DAO_Internal); + } + else if (aParamValue == "fit") + { + anAspect->SetArrowOrientation (Prs3d_DAO_Fit); + } + } + else + { + std::cerr << theArgVec[0] << ": unknow parameter: \"" << aParamName << "\".\n"; + return 1; + } + } + } + + // Redisplay a dimension after parameter changing. + ViewerTest::GetAISContext()->Redisplay (aDim); + return 0; +} + //======================================================================= //function : VMoveDim -//purpose : +//purpose : Moves dimension or relation text label to defined or picked +// position and updates the object. +//draw args: vmovedim [name] [x y z] //======================================================================= -static int VMoveDim(Draw_Interpretor& di, Standard_Integer argc, const char** argv) +static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec) { - if(argc>2) return 1; - - const Handle(V3d_View) aview = ViewerTest::CurrentView(); - Handle(AIS_InteractiveObject) pickedobj; - if(argc==1){ - pickedobj = TheAISContext()->FirstCurrentObject(); - if(pickedobj.IsNull() || pickedobj->Type()!=AIS_KOI_Relation) - pickedobj = ViewerTest::PickObject(AIS_KOI_Relation); - } - else{ - // reperage dans le viewer... - if(!strcasecmp(argv[1],".")){ - pickedobj = ViewerTest::PickObject(AIS_KOI_Relation); - - } - else if(GetMapOfAIS().IsBound2(argv[1])) - pickedobj = Handle(AIS_InteractiveObject)::DownCast - (GetMapOfAIS().Find2(argv[1])); - } - - if(pickedobj.IsNull()){ - di<<"Bad Type Object"<<"\n"; - return 1 ;} - - if(pickedobj->Type() != AIS_KOI_Relation) + if (theArgNum > 5) + { + theDi << theArgVec[0] << " error: the wrong number of parameters.\n"; return 1; - Standard_Integer argccc = 5; - - const char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; - const char **argvvv = (const char **) bufff; + } - Handle(AIS_Relation) R = *((Handle(AIS_Relation)*)&pickedobj); - Handle(Geom_Plane) ThePl; -// Standard_Real x,y,z,xv,yv,zv; - Standard_Real x,y,xv,yv,zv; - static Standard_Real last_xv(0),last_yv(0),last_zv(0); - Standard_Integer xpix,ypix; -// Standard_Boolean SameAsLast(Standard_False); - Select3D_Projector prj(aview); - - - while (ViewerMainLoop( argccc, argvvv) ) { - //....... la ligne de tir - ViewerTest::GetMousePosition(xpix,ypix); - aview->Convert(xpix,ypix,x,y); // espace reel 2D de la vue... - gp_Lin L = prj.Shoot(x,y); + // Parameters parsing + Standard_Boolean isNameSet = (theArgNum ==2 || theArgNum == 5); + Standard_Boolean isPointSet = (theArgNum == 4 || theArgNum == 5); - - - // ....... le plan de la vue... - aview->Proj(xv,yv,zv); - static Standard_Boolean haschanged(Standard_False); - if(Abs(last_xv-xv)>Precision::Confusion() || - Abs(last_yv-yv)>Precision::Confusion() || - Abs(last_zv-zv)>Precision::Confusion() ){ - last_xv = xv; - last_yv = yv; - last_zv = zv; - Standard_Real xat,yat,zat; - aview->At(xat,yat,zat); - ThePl = new Geom_Plane(gp_Pnt(xat,yat,zat),gp_Dir(xv,yv,zv)); - haschanged = Standard_True; - di <<"changement de plan"<<"\n"; - } - - // -// Standard_Integer xpix,ypix; -// Standard_Real x,y; - gp_Pnt GoodPoint; - if(haschanged){ - gp_Pln NewPlane;; - ComputeNewPlaneForDim(R,NewPlane,GoodPoint); - haschanged = Standard_False; - } - else{ - if(ComputeIntersection(L,ThePl->Pln(),GoodPoint)){ - R->SetPosition(GoodPoint); + Handle(AIS_InteractiveObject) aPickedObj; + gp_Pnt aPoint (gp::Origin()); + Standard_Integer aCurrentIndex = 0; + Standard_Integer aMaxPickNum = 5; + + // Find object + if (isNameSet) + { + TCollection_AsciiString aName (theArgVec[1]); + if (!GetMapOfAIS().IsBound2 (aName)) + { + theDi << theArgVec[0] << " error: no object with this name.\n"; + return 1; + } + + aPickedObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName)); + + if (aPickedObj.IsNull()) + { + theDi << theArgVec[0] << " error: the object with this name is not valid.\n"; + return 1; + } + + if (aPickedObj->Type() != AIS_KOI_Dimension && aPickedObj->Type() != AIS_KOI_Relation) + { + theDi << theArgVec[0] << " error: no dimension or relation with this name.\n"; + return 1; + } + } + else // Pick dimension or relation + { + // Close all local contexts + TheAISContext()->CloseAllContexts(); + + // Open local context and get its index for recovery. + TheAISContext()->OpenLocalContext(); + aCurrentIndex = TheAISContext()->IndexOfCurrentLocal(); + + // Loop that will be handle picking. + Standard_Integer anArgNum = 5; + const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" }; + const char **anArgVec = (const char **) aBuffer; + + Standard_Boolean isPicked = Standard_False; + Standard_Integer aPickNum = 0; + while (!isPicked && aPickNum < aMaxPickNum) + { + while (ViewerMainLoop (anArgNum, anArgVec)) { } + + for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected()) + { + aPickedObj = TheAISContext()->SelectedInteractive(); } - TheAISContext()->Redisplay(R); + + isPicked = (!aPickedObj.IsNull() && (aPickedObj->Type() == AIS_KOI_Dimension || aPickedObj->Type() == AIS_KOI_Relation)); + + if (isPicked) + { + break; + } + aPickNum++; + } + if (!isPicked) + { + theDi << theArgVec[0] << ": no dimension or relation is selected." << "\n"; + return 1; } } - + + // Find point + if (isPointSet) + { + aPoint = theArgNum == 4 ? gp_Pnt (atoi (theArgVec[1]), atoi (theArgVec[2]), atoi (theArgVec[3])) + : gp_Pnt (atoi (theArgVec[2]), atoi (theArgVec[3]), atoi (theArgVec[4])); + } + else // Pick the point + { + Standard_Integer aPickArgNum = 5; + const char *aPickBuff[] = {"VPick", "X", "VPickY", "VPickZ", "VPickShape"}; + const char **aPickArgVec = (const char **) aPickBuff; + + while (ViewerMainLoop (aPickArgNum, aPickArgVec)) { } + + // Set text position, update relation or dimension. + if (aPickedObj->Type() == AIS_KOI_Relation) + { + Handle(AIS_Relation) aRelation = Handle(AIS_Relation)::DownCast (aPickedObj); + aPoint = Get3DPointAtMousePosition(); + aRelation->SetPosition (aPoint); + TheAISContext()->Redisplay (aRelation); + } + else + { + Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (aPickedObj); + gp_Pnt aFirstPoint, aSecondPoint; + if (aDim->KindOfDimension() == AIS_KOD_PLANEANGLE) + { + Handle(AIS_AngleDimension) anAngleDim = Handle(AIS_AngleDimension)::DownCast (aDim); + aFirstPoint = anAngleDim->FirstPoint(); + aSecondPoint = anAngleDim->SecondPoint(); + } + else if (aDim->KindOfDimension() == AIS_KOD_LENGTH) + { + Handle(AIS_LengthDimension) aLengthDim = Handle(AIS_LengthDimension)::DownCast (aDim); + aFirstPoint = aLengthDim->FirstPoint(); + aSecondPoint = aLengthDim->SecondPoint(); + } + else if (aDim->KindOfDimension() == AIS_KOD_RADIUS) + { + Handle(AIS_RadiusDimension) aRadiusDim = Handle(AIS_RadiusDimension)::DownCast (aDim); + aFirstPoint = aRadiusDim->AnchorPoint(); + aSecondPoint = aRadiusDim->Circle().Location(); + } + else if (aDim->KindOfDimension() == AIS_KOD_DIAMETER) + { + Handle(AIS_DiameterDimension) aDiameterDim = Handle(AIS_DiameterDimension)::DownCast (aDim); + aFirstPoint = aDiameterDim->AnchorPoint(); + aSecondPoint = aDiameterDim->Circle().Location(); + } + + if (!Get3DPointAtMousePosition (aFirstPoint, aSecondPoint, aPoint)) + { + return 1; + } + + aDim->SetTextPosition (aPoint); + TheAISContext()->Redisplay (aDim); + } + + } + + // Set text position, update relation or dimension. + if (aPickedObj->Type() == AIS_KOI_Relation) + { + Handle(AIS_Relation) aRelation = Handle(AIS_Relation)::DownCast (aPickedObj); + aRelation->SetPosition (aPoint); + TheAISContext()->Redisplay (aRelation); + } + else + { + Handle(AIS_Dimension) aDim = Handle(AIS_Dimension)::DownCast (aPickedObj); + aDim->SetTextPosition (aPoint); + TheAISContext()->Redisplay (aDim); + } + return 0; } @@ -2504,9 +2693,17 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands) " [text={2d|3d}] [plane={xoy|yoz|zox}]\n" " [label={left|right|hcenter|hfit},{above|below|vcenter}]\n" " [flyout=value] [arrows={external|internal|fit}]\n" - " -Builds angle, length, radius and diameter dimensions.\n" + " -Builds angle, length, radius and diameter dimensions.\n", __FILE__,VDimBuilder,group); + theCommands.Add("vdimparam", + "vdimparam Dim_Name" + " [text={2d|3d}] [plane={xoy|yoz|zox}]\n" + " [label={left|right|hcenter|hfit},{above|below|vcenter}]\n" + " [flyout=value] [arrows={external|internal|fit}]\n" + " -Sets parameters for angle, length, radius and diameter dimensions.\n", + __FILE__,VDimParam,group); + theCommands.Add("vangledim", "vangledim Name:Selection in the viewer only ", __FILE__,VAngleDimBuilder,group); diff --git a/tests/bugs/vis/bug24412_1 b/tests/bugs/vis/bug24412_1 new file mode 100644 index 0000000000..d26de813d9 --- /dev/null +++ b/tests/bugs/vis/bug24412_1 @@ -0,0 +1,48 @@ +puts "============" +puts "CR24412" +puts "============" +puts "" +####################################################################### +# TKV3d, Dimensions - Possibility to customize text position was lost +# Test position setting for linear dimension +####################################################################### +pload ALL + +set anImage1 $imagedir/${casename}_1.png +set anImage2 $imagedir/${casename}_2.png + +vinit Viewer1/View1 +vpoint circ_p1 0 10 30 +vpoint circ_p2 30 10 0 +vpoint circ_p3 60 10 30 +vcircle circ circ_p1 circ_p2 circ_p3 0 +vdisplay circ +vdimension diameter name=diam circ +vdisplay diam +# Change text position +vmovedim diam 15 15 15 +vfit + +# Check that text position was changed and the text is not aligned +set x_coord 166 +set y_coord 226 +checkcolor $x_coord $y_coord 0.46 0.9 0 +if { $stat != 1 } { + puts "Error : Text position of dimension is incorrect." +} + +vdump $anImage1 + +# Update dimension parameters and set automatic text positioning +vdimparam diam flyout=-5 +vfit + +# Check that text position was changed according to flyout +set x_coord 213 +set y_coord 179 +checkcolor $x_coord $y_coord 0.46 0.9 0 +if { $stat != 1 } { + puts "Error : Text position of dimension after layout changing is incorrect." +} + +vdump $anImage2 diff --git a/tests/bugs/vis/bug24412_2 b/tests/bugs/vis/bug24412_2 new file mode 100644 index 0000000000..a51f3e2900 --- /dev/null +++ b/tests/bugs/vis/bug24412_2 @@ -0,0 +1,46 @@ +puts "============" +puts "CR24412" +puts "============" +puts "" +####################################################################### +# TKV3d, Dimensions - Possibility to customize text position was lost +# Test position setting for angular dimension +####################################################################### +pload ALL + +set anImage1 $imagedir/${casename}_1.png +set anImage2 $imagedir/${casename}_2.png + +vinit Viewer1/View1 +vpoint ang_p1 0 0 30 +vpoint ang_p2 30 0 0 +vpoint ang_p3 60 0 30 +vdimension angle name=ang ang_p1 ang_p2 ang_p3 +vdisplay ang +vmovedim ang 5 0 5 +vfit + +# Check that text position was changed and the text is not aligned +set x_coord 60 +set y_coord 189 +checkcolor $x_coord $y_coord 0.46 0.9 0 +if { $stat != 1 } { + puts "Error : Text position of dimension is incorrect." +} + +vdump $anImage1 + + +# Update dimension parameters and set automatic text positioning +vdimparam ang flyout=-5 +vfit + +# Check that text position was changed according to flyout +set x_coord 206 +set y_coord 312 +checkcolor $x_coord $y_coord 0.46 0.9 0 +if { $stat != 1 } { + puts "Error : Text position of dimension after layout changing is incorrect." +} + +vdump $anImage2