From: azv Date: Mon, 9 Dec 2019 12:26:44 +0000 (+0300) Subject: Task 5.1.3 Sketcher: angle dimension (issue #3061) X-Git-Tag: V9_5_0a1~112 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=75d834b478d59310d80b93a125f064bfa80cc549;p=modules%2Fshaper.git Task 5.1.3 Sketcher: angle dimension (issue #3061) Movement of Angle presentation. --- diff --git a/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp b/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp index bf2f211d9..2e76e2a4e 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp @@ -72,6 +72,12 @@ void SketchPlugin_ConstraintAngle::initAttributes() data()->addAttribute(LOCATION_TYPE_ID(), ModelAPI_AttributeInteger::typeId()); aValidators->registerNotObligatory(getKind(), LOCATION_TYPE_ID()); + data()->addAttribute(PREV_TYPE_ID(), ModelAPI_AttributeInteger::typeId()); + data()->attribute(PREV_TYPE_ID())->setIsArgument(false); + aValidators->registerNotObligatory(getKind(), PREV_TYPE_ID()); + if (attribute(TYPE_ID())->isInitialized()) + integer(PREV_TYPE_ID())->setValue(integer(TYPE_ID())->value()); + data()->addAttribute(SELECTED_FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId()); data()->attribute(SELECTED_FIRST_POINT_ID())->setIsArgument(false); aValidators->registerNotObligatory(getKind(), SELECTED_FIRST_POINT_ID()); @@ -79,11 +85,6 @@ void SketchPlugin_ConstraintAngle::initAttributes() data()->addAttribute(SELECTED_SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId()); data()->attribute(SELECTED_SECOND_POINT_ID())->setIsArgument(false); aValidators->registerNotObligatory(getKind(), SELECTED_SECOND_POINT_ID()); - - if (attribute(TYPE_ID())->isInitialized()) - myPrevAngleType = integer(TYPE_ID())->value(); - else - myPrevAngleType = (int)SketcherPrs_Tools::ANGLE_DIRECT; } void SketchPlugin_ConstraintAngle::colorConfigInfo(std::string& theSection, std::string& theName, @@ -131,6 +132,9 @@ AISObjectPtr SketchPlugin_ConstraintAngle::getAISObject(AISObjectPtr thePrevious void SketchPlugin_ConstraintAngle::attributeChanged(const std::string& theID) { + if (myFlyoutUpdate) + return; + std::shared_ptr aData = data(); if (!aData) return; @@ -146,25 +150,8 @@ void SketchPlugin_ConstraintAngle::attributeChanged(const std::string& theID) if (theID == ENTITY_A() || theID == ENTITY_B() || theID == TYPE_ID() || theID == ANGLE_VALUE_ID()) { calculateAngle(); - } else if (theID == FLYOUT_VALUE_PNT() && !myFlyoutUpdate) { - // Recalculate flyout point in local coordinates - // coordinates are calculated according to the center of shapes intersection - std::shared_ptr aFlyoutAttr = - std::dynamic_pointer_cast(attribute(FLYOUT_VALUE_PNT())); - - std::shared_ptr aData = data(); - std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); - - // Intersection of lines - std::shared_ptr anInter = intersect(aLineA, aLineB); - if (!anInter) - return; - - myFlyoutUpdate = true; - std::shared_ptr aFlyoutDir = aFlyoutAttr->pnt()->xy()->decreased(anInter->xy()); - if (aFlyoutDir->dot(aFlyoutDir) < tolerance * tolerance) - aFlyoutAttr->setValue(aFlyoutAttr->x() + tolerance, aFlyoutAttr->y()); - myFlyoutUpdate = false; + } else if (theID == FLYOUT_VALUE_PNT()) { + compute(theID); } } @@ -189,16 +176,18 @@ void SketchPlugin_ConstraintAngle::calculateAngle() bool isReversed1 = boolean(ANGLE_REVERSED_FIRST_LINE_ID())->value(); bool isReversed2 = boolean(ANGLE_REVERSED_SECOND_LINE_ID())->value(); - std::shared_ptr anAng( - new GeomAPI_Angle2d(aLine1, isReversed1, aLine2, isReversed2)); - double anAngle = anAng->angleDegree(); - AttributeDoublePtr anAngleValueAttr = real(ANGLE_VALUE_ID()); - if (!anAngleValueAttr->isInitialized()) - anAngleValueAttr->setValue(getAngleForType(fabs(anAngle))); + if (!anAngleValueAttr->isInitialized()) { + std::shared_ptr anAng( + new GeomAPI_Angle2d(aLine1, isReversed1, aLine2, isReversed2)); + anAngleValueAttr->setValue(getAngleForType(fabs(anAng->angleDegree()))); + } + + std::shared_ptr anAng(new GeomAPI_Angle2d(aLine1, false, aLine2, false)); + double anAngle = anAng->angleDegree(); anAngle /= fabs(anAngle); - anAngle *= getAngleForType(anAngleValueAttr->value()); + anAngle *= getAngleForType(anAngleValueAttr->value(), isReversed1, isReversed2); // update value of the constraint to be passed to the solver real(SketchPlugin_Constraint::VALUE())->setValue(anAngle); @@ -252,6 +241,7 @@ void SketchPlugin_ConstraintAngle::calculateAnglePosition() boolean(ANGLE_REVERSED_SECOND_LINE_ID())->setValue(isReversed2); } +// Convert angle value from the DIRECT to any given type. static double angleForType(const double theAngle, const int theType) { double anAngle = theAngle; @@ -271,27 +261,32 @@ static double angleForType(const double theAngle, const int theType) return anAngle; } -double SketchPlugin_ConstraintAngle::getAngleForType(double theAngle) +double SketchPlugin_ConstraintAngle::getAngleForType(double theAngle, + bool isReversed1, + bool isReversed2) { - return angleForType(theAngle, integer(TYPE_ID())->value()); + double anAngle = angleForType(theAngle, integer(TYPE_ID())->value()); + if (isReversed1 != isReversed2) + anAngle = 180.0 - anAngle; + return anAngle; } -void SketchPlugin_ConstraintAngle::updateAngleValue() +// Convert angle value or a text expression from one angle type to another +static void convertAngle(AttributeDoublePtr& theAngle, + const int thePrevType, const int theNewType) { - AttributeIntegerPtr anAngleType = integer(TYPE_ID()); - AttributeDoublePtr anAngleValueAttr = real(ANGLE_VALUE_ID()); - if (anAngleValueAttr->isInitialized()) { - if (anAngleValueAttr->text().empty()) { + if (theAngle->isInitialized()) { + if (theAngle->text().empty()) { // calculate value related to the type twice: // the first time - to return to direct angle, // the second time - to apply new type - double aValue = angleForType(anAngleValueAttr->value(), myPrevAngleType); - aValue = angleForType(aValue, anAngleType->value()); - anAngleValueAttr->setValue(aValue); + double aValue = angleForType(theAngle->value(), thePrevType); + aValue = angleForType(aValue, theNewType); + theAngle->setValue(aValue); } else { // process the parametric value - std::string anAngleText = anAngleValueAttr->text(); + std::string anAngleText = theAngle->text(); std::regex anAngleRegex("\\s*([-+]?[0-9]*\\.?[0-9]*)\\s*([-+])\\s*\\((.*)\\)", std::regex_constants::ECMAScript); @@ -306,13 +301,13 @@ void SketchPlugin_ConstraintAngle::updateAngleValue() anAngleText = aResult[3].str(); } - if (myPrevAngleType != SketcherPrs_Tools::ANGLE_DIRECT) + if (thePrevType != SketcherPrs_Tools::ANGLE_DIRECT) aSignInd = 1 - aSignInd; - anAnglePrefix = angleForType(anAnglePrefix, myPrevAngleType); + anAnglePrefix = angleForType(anAnglePrefix, thePrevType); - if (anAngleType->value() != SketcherPrs_Tools::ANGLE_DIRECT) + if (theNewType != SketcherPrs_Tools::ANGLE_DIRECT) aSignInd = 1 - aSignInd; - anAnglePrefix = angleForType(anAnglePrefix, anAngleType->value()); + anAnglePrefix = angleForType(anAnglePrefix, theNewType); std::ostringstream aText; bool isPrintSign = true; @@ -323,10 +318,17 @@ void SketchPlugin_ConstraintAngle::updateAngleValue() if (isPrintSign) aText << " " << aSignPrefix[aSignInd] << " ("; aText << anAngleText << (isPrintSign ? ")" : ""); - anAngleValueAttr->setText(aText.str()); + theAngle->setText(aText.str()); } } - myPrevAngleType = anAngleType->value(); +} + +void SketchPlugin_ConstraintAngle::updateAngleValue() +{ + AttributeIntegerPtr anAngleType = integer(TYPE_ID()); + AttributeIntegerPtr aPrevAngleType = integer(PREV_TYPE_ID()); + convertAngle(real(ANGLE_VALUE_ID()), aPrevAngleType->value(), anAngleType->value()); + aPrevAngleType->setValue(anAngleType->value()); } bool SketchPlugin_ConstraintAngle::compute(const std::string& theAttributeId) @@ -338,34 +340,75 @@ bool SketchPlugin_ConstraintAngle::compute(const std::string& theAttributeId) std::shared_ptr aFlyOutAttr = std::dynamic_pointer_cast< GeomDataAPI_Point2D>(attribute(theAttributeId)); - if (aFlyOutAttr->isInitialized() && - (fabs(aFlyOutAttr->x()) >= tolerance || fabs(aFlyOutAttr->y()) >= tolerance)) - return false; DataPtr aData = data(); std::shared_ptr aPlane = SketchPlugin_Sketch::plane(sketch()); - FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A()); - FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B()); + FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_A()); + FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_B()); if ((aLineA.get() == NULL) || (aLineB.get() == NULL)) return false; - // Start and end points of lines - GeomPnt2dPtr aStartA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::START_ID()); - GeomPnt2dPtr aEndA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::END_ID()); - if (aStartA->distance(aEndA) < tolerance) + // Intersection of lines + std::shared_ptr anInter = intersect(aLineA, aLineB); + if (!anInter) return false; - GeomPnt2dPtr aStartB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::START_ID()); - GeomPnt2dPtr aEndB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::END_ID()); - if (aStartB->distance(aEndB) < tolerance) - return false; + bool isReversed1 = boolean(ANGLE_REVERSED_FIRST_LINE_ID())->value(); + bool isReversed2 = boolean(ANGLE_REVERSED_SECOND_LINE_ID())->value(); + + int anAngleType = integer(TYPE_ID())->value(); + + bool isSupplementary = anAngleType == (int)SketcherPrs_Tools::ANGLE_COMPLEMENTARY; + + // point on lines to compose an angle + GeomPnt2dPtr aPointA = SketcherPrs_Tools::getPoint(aLineA.get(), + (isReversed1 ^ isSupplementary) ? + SketchPlugin_Line::START_ID() : SketchPlugin_Line::END_ID()); + GeomPnt2dPtr aPointB = SketcherPrs_Tools::getPoint(aLineB.get(), + isReversed2 ? SketchPlugin_Line::START_ID() : SketchPlugin_Line::END_ID()); myFlyoutUpdate = true; - double aX = (aStartA->x() + aEndA->x() + aStartB->x() + aEndB->x()) / 4.; - double aY = (aStartA->y() + aEndA->y() + aStartB->y() + aEndB->y()) / 4.; + if (aFlyOutAttr->isInitialized()) { + std::shared_ptr aFlyoutPoint = aFlyOutAttr->pnt()->xy(); + std::shared_ptr anInterXY = anInter->xy(); + std::shared_ptr aDirIF = aFlyoutPoint->decreased(anInterXY); + std::shared_ptr aDirIA = aPointA->xy()->decreased(anInterXY); + std::shared_ptr aDirIB = aPointB->xy()->decreased(anInterXY); + double aSign = aDirIA->cross(aDirIB); + aSign /= fabs(aSign); + if (anAngleType == (int)SketcherPrs_Tools::ANGLE_BACKWARD) + aSign *= -1.0; + + double cross1 = aSign * aDirIA->cross(aDirIF); + if (cross1 < -tolerance) + boolean(ANGLE_REVERSED_SECOND_LINE_ID())->setValue(!isReversed2); + double cross2 = aSign * aDirIF->cross(aDirIB); + if (cross2 < -tolerance) + boolean(ANGLE_REVERSED_FIRST_LINE_ID())->setValue(!isReversed1); + + // the direction is reversed only once + if ((cross1 + tolerance) * (cross2 + tolerance) < 0.0) { + if (anAngleType == (int)SketcherPrs_Tools::ANGLE_BACKWARD) { + convertAngle(real(ANGLE_VALUE_ID()), (int)SketcherPrs_Tools::ANGLE_BACKWARD, + (int)SketcherPrs_Tools::ANGLE_DIRECT); + } + convertAngle(real(ANGLE_VALUE_ID()), (int)SketcherPrs_Tools::ANGLE_DIRECT, + (int)SketcherPrs_Tools::ANGLE_COMPLEMENTARY); + if (anAngleType == (int)SketcherPrs_Tools::ANGLE_BACKWARD) { + convertAngle(real(ANGLE_VALUE_ID()), (int)SketcherPrs_Tools::ANGLE_DIRECT, + (int)SketcherPrs_Tools::ANGLE_BACKWARD); + } + } - aFlyOutAttr->setValue(aX, aY); + calculateAngle(); + } + else { + // default position of the presentation + double aX = (aPointA->x() + aPointB->x() + anInter->x()) / 3.; + double aY = (aPointA->y() + aPointB->y() + anInter->y()) / 3.; + aFlyOutAttr->setValue(aX, aY); + } myFlyoutUpdate = false; return true; diff --git a/src/SketchPlugin/SketchPlugin_ConstraintAngle.h b/src/SketchPlugin/SketchPlugin_ConstraintAngle.h index 3983acff6..71bd34607 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintAngle.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintAngle.h @@ -53,6 +53,12 @@ class SketchPlugin_ConstraintAngle : public SketchPlugin_ConstraintBase static const std::string MY_TYPE_ID("AngleType"); return MY_TYPE_ID; } + /// attribute name of previous value of operation type + inline static const std::string& PREV_TYPE_ID() + { + static const std::string MY_TYPE_ID("AngleTypePrevious"); + return MY_TYPE_ID; + } /// attribute name of operation type inline static const std::string& ANGLE_VALUE_ID() @@ -131,14 +137,13 @@ protected: /// The in/out angle is in degree. /// \param theAngle a source for the calculated angle /// \param a double angle value - double getAngleForType(double theAngle); + double getAngleForType(double theAngle, bool isReversed1 = false, bool isReversed2 = false); /// Update value of ANGLE_VALUE attribute according to the current type void updateAngleValue(); private: bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point - int myPrevAngleType; }; #endif diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index a13a7b891..a438391ab 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -602,19 +602,10 @@ ConstraintWrapperPtr createConstraintAngle( std::shared_ptr theEntity2) { std::shared_ptr aLine1 = std::dynamic_pointer_cast(theEntity1->entity()); - bool isLine1Rev = theConstraint->boolean( - SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value(); - GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1; - GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2; - std::shared_ptr aLine2 = std::dynamic_pointer_cast(theEntity2->entity()); - bool isLine2Rev = theConstraint->boolean( - SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value(); - GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1; - GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2; GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle( - aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar())); + aLine1->p1, aLine1->p2, aLine2->p1, aLine2->p2, theValue->scalar())); std::shared_ptr aResult( new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE)); diff --git a/src/SketcherPrs/SketcherPrs_Angle.cpp b/src/SketcherPrs/SketcherPrs_Angle.cpp index 1696fc7e1..9edc95a76 100644 --- a/src/SketcherPrs/SketcherPrs_Angle.cpp +++ b/src/SketcherPrs/SketcherPrs_Angle.cpp @@ -91,6 +91,8 @@ bool SketcherPrs_Angle::readyToDisplay(ModelAPI_Feature* theConstraint, gp_Pnt& theCenterPoint) { bool aReadyToDisplay = false; + if (!thePlane) + return aReadyToDisplay; DataPtr aData = theConstraint->data(); @@ -141,6 +143,11 @@ bool SketcherPrs_Angle::readyToDisplay(ModelAPI_Feature* theConstraint, std::shared_ptr aLine2(new GeomAPI_Lin2d(aStartB->pnt(), aEndB->pnt())); bool isReversed2 = aData->boolean(SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value(); + + if (aData->integer(SketchPlugin_ConstraintAngle::TYPE_ID())->value() == + (int)SketcherPrs_Tools::ANGLE_COMPLEMENTARY) + isReversed1 = !isReversed1; + anAng = std::shared_ptr( new GeomAPI_Angle2d(aLine1, isReversed1, aLine2, isReversed2)); } @@ -156,6 +163,9 @@ bool SketcherPrs_Angle::readyToDisplay(ModelAPI_Feature* theConstraint, aSecondPoint = anAng->firstPoint()->impl(); } + if (aData->integer(SketchPlugin_ConstraintAngle::TYPE_ID())->value() == + (int)SketcherPrs_Tools::ANGLE_BACKWARD) + std::swap(aFirstPoint, aSecondPoint); std::shared_ptr aPoint = thePlane->to3D(aFirstPoint.X(), aFirstPoint.Y()); theFirstPoint = aPoint->impl(); @@ -199,48 +209,15 @@ void SketcherPrs_Angle::Compute(const Handle(PrsMgr_PresentationManager3d)& theP myFlyOutPoint = aFlyoutPnt->impl(); } - std::shared_ptr aTypeAttr = std::dynamic_pointer_cast< - ModelAPI_AttributeInteger>(aData->attribute(SketchPlugin_ConstraintAngle::TYPE_ID())); - SketcherPrs_Tools::AngleType anAngleType = (SketcherPrs_Tools::AngleType)(aTypeAttr->value()); - double aDist = -1; - switch (anAngleType) { - case SketcherPrs_Tools::ANGLE_DIRECT: { -#ifndef COMPILATION_CORRECTION - SetArrowsVisibility(AIS_TOAV_Both); -#endif - SetMeasuredGeometry(myFirstPoint, myCenterPoint, mySecondPoint); -#ifndef COMPILATION_CORRECTION - bool isReversedPlanes = isAnglePlaneReversedToSketchPlane(); - SetType(!isReversedPlanes ? AIS_TOA_Exterior : AIS_TOA_Interior); -#endif - } - break; - case SketcherPrs_Tools::ANGLE_COMPLEMENTARY: { - double anEdge1Length = aCenterPoint.Distance(myFirstPoint); - //aDist = calculateDistanceToFlyoutPoint(); - gp_Pnt aFirstPoint = aCenterPoint.Translated( - gp_Vec(myCenterPoint, myFirstPoint).Normalized() * (-anEdge1Length)); - SetMeasuredGeometry(aFirstPoint, myCenterPoint, mySecondPoint); #ifndef COMPILATION_CORRECTION - SetType(AIS_TOA_Interior); + SetArrowsVisibility(AIS_TOAV_Both); #endif - } - break; - case SketcherPrs_Tools::ANGLE_BACKWARD: { + SetMeasuredGeometry(myFirstPoint, myCenterPoint, mySecondPoint); #ifndef COMPILATION_CORRECTION - SetArrowsVisibility(AIS_TOAV_Both); + bool isReversedPlanes = isAnglePlaneReversedToSketchPlane(); + SetType(!isReversedPlanes ? AIS_TOA_Exterior : AIS_TOA_Interior); #endif - SetMeasuredGeometry(myFirstPoint, myCenterPoint, mySecondPoint); - bool isReversedPlanes = isAnglePlaneReversedToSketchPlane(); -#ifndef COMPILATION_CORRECTION - SetType(isReversedPlanes ? AIS_TOA_Exterior : AIS_TOA_Interior); -#endif - } - break; - default: - break; - } if (aDist < 0) /// it was not calculated yet aDist = calculateDistanceToFlyoutPoint(); SetFlyout(aDist);