X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_ConstraintAngle.cpp;h=7874be39513f2c17c99082de801dbabbed27d366;hb=64fc7e4fdd63997ec7a502b233ef5f88186d5bbb;hp=c298122ba5299b4766a0b60a437306938a6b1e64;hpb=4df3d12284892e126685f42a4e3c3c7f63f3b502;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp b/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp index c298122ba..7874be395 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintAngle.cpp @@ -18,12 +18,18 @@ #include #include +#include + const double tolerance = 1.e-7; #define PI 3.1415926535897932 +/// \brief Calculate intersection point of two lines +static std::shared_ptr intersect(FeaturePtr theLine1, FeaturePtr theLine2); + SketchPlugin_ConstraintAngle::SketchPlugin_ConstraintAngle() { + myFlyoutUpdate = false; } void SketchPlugin_ConstraintAngle::initAttributes() @@ -31,19 +37,32 @@ void SketchPlugin_ConstraintAngle::initAttributes() data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId()); } void SketchPlugin_ConstraintAngle::execute() { std::shared_ptr aData = data(); - AttributeDoublePtr anAttrValue = std::dynamic_pointer_cast( - aData->attribute(SketchPlugin_Constraint::VALUE())); - if(anAttrValue->isInitialized()) + std::shared_ptr anAttrA = aData->refattr(SketchPlugin_Constraint::ENTITY_A()); + std::shared_ptr anAttrB = aData->refattr(SketchPlugin_Constraint::ENTITY_B()); + if (!anAttrA->isInitialized() || !anAttrB->isInitialized()) return; - double anAngle = calculateAngle(); - anAttrValue->setValue(anAngle); + AttributeDoublePtr anAttrValue = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::VALUE())); + + if (!anAttrValue->isInitialized()) { + double anAngle = calculateAngle(); + anAttrValue->setValue(anAngle); + } + // the value should to be computed here, not in the getAISObject in order to change the model value + // inside the object transaction. This is important for creating a constraint by preselection. + // The display of the presentation in this case happens after the transaction commit + std::shared_ptr aFlyOutAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + if(!aFlyOutAttr->isInitialized()) + compute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()); } AISObjectPtr SketchPlugin_ConstraintAngle::getAISObject(AISObjectPtr thePrevious) @@ -55,27 +74,53 @@ AISObjectPtr SketchPlugin_ConstraintAngle::getAISObject(AISObjectPtr thePrevious if (!anAIS) { anAIS = SketcherPrs_Factory::angleConstraint(this, sketch()->coordinatePlane()); } + + // Set color from preferences + std::vector aRGB = Config_PropManager::color("Visualization", "sketch_dimension_color", + SKETCH_DIMENSION_COLOR); + anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]); return anAIS; } void SketchPlugin_ConstraintAngle::attributeChanged(const std::string& theID) { - if (theID == SketchPlugin_Constraint::ENTITY_A() || - theID == SketchPlugin_Constraint::ENTITY_B()) { - std::shared_ptr aData = data(); - if (!aData) - return; + std::shared_ptr aData = data(); + if (!aData) + return; FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A()); FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B()); - if (!aLineA || !aLineB) - return; + if (!aLineA || !aLineB) + return; + if (theID == SketchPlugin_Constraint::ENTITY_A() || + theID == SketchPlugin_Constraint::ENTITY_B()) { std::shared_ptr aValueAttr = std::dynamic_pointer_cast< ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE())); if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value double anAngle = calculateAngle(); aValueAttr->setValue(anAngle); } + } else if (theID == SketchPlugin_Constraint::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(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + + std::shared_ptr 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()); + + // 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; } } @@ -88,6 +133,11 @@ double SketchPlugin_ConstraintAngle::calculateAngle() FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A()); FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B()); + // Intersection of lines + std::shared_ptr anInter = intersect(aLineA, aLineB); + if (!anInter) + return anAngle; + // Start and end points of lines std::shared_ptr aPointA1 = std::dynamic_pointer_cast( aLineA->attribute(SketchPlugin_Line::START_ID())); @@ -103,24 +153,113 @@ double SketchPlugin_ConstraintAngle::calculateAngle() std::shared_ptr aEndA = aPointA2->pnt(); std::shared_ptr aStartB = aPointB1->pnt(); std::shared_ptr aEndB = aPointB2->pnt(); - if (aStartA->distance(aEndA) < tolerance || aStartB->distance(aEndB) < tolerance) - return anAngle; - // Lines and their intersection point - std::shared_ptr aLA(new GeomAPI_Lin2d(aStartA, aEndA)); - std::shared_ptr aLB(new GeomAPI_Lin2d(aStartB, aEndB)); - std::shared_ptr anInter = aLA->intersect(aLB); - if (!anInter) - return anAngle; + double aDist[2][2] = { + { anInter->distance(aStartA), anInter->distance(aEndA) }, + { anInter->distance(aStartB), anInter->distance(aEndB) } + }; // Directions of lines - if (anInter->distance(aEndA) < tolerance) + if (aDist[0][1] < tolerance) aEndA = aStartA; - if (anInter->distance(aEndB) < tolerance) + if (aDist[1][1] < tolerance) aEndB = aStartB; std::shared_ptr aDirA(new GeomAPI_Dir2d(aEndA->xy()->decreased(anInter->xy()))); std::shared_ptr aDirB(new GeomAPI_Dir2d(aEndB->xy()->decreased(anInter->xy()))); - anAngle = aDirA->angle(aDirB) * 180.0 / PI; + anAngle = fabs(aDirA->angle(aDirB)) * 180.0 / PI; + + // If the lines intersected inside one of them, the angle selected is less than 90 degrees + if ((aDist[0][0] >= tolerance && aDist[0][1] >= tolerance && + aDist[0][0] + aDist[0][1] < aStartA->distance(aEndA) + 2.0 * tolerance) || + (aDist[1][0] >= tolerance && aDist[1][1] >= tolerance && + aDist[1][0] + aDist[1][1] < aStartB->distance(aEndB) + 2.0 * tolerance)) { + if (anAngle > 90.0) + anAngle = 180.0 - anAngle; + } + return anAngle; } + +void SketchPlugin_ConstraintAngle::move(double theDeltaX, double theDeltaY) +{ + std::shared_ptr aData = data(); + if (!aData->isValid()) + return; + + myFlyoutUpdate = true; + std::shared_ptr aFlyoutAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT())); + aFlyoutAttr->setValue(aFlyoutAttr->x() + theDeltaX, aFlyoutAttr->y() + theDeltaY); + myFlyoutUpdate = false; +} + + +bool SketchPlugin_ConstraintAngle::compute(const std::string& theAttributeId) +{ + if (theAttributeId != SketchPlugin_Constraint::FLYOUT_VALUE_PNT()) + return false; + if (!sketch()) + return false; + + std::shared_ptr aFlyOutAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(attribute(theAttributeId)); + if (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()); + + if ((aLineA.get() == NULL) || (aLineB.get() == NULL)) + return false; + + // Start and end points of lines + std::shared_ptr aPointA1 = std::dynamic_pointer_cast( + aLineA->attribute(SketchPlugin_Line::START_ID())); + std::shared_ptr aPointA2 = std::dynamic_pointer_cast( + aLineA->attribute(SketchPlugin_Line::END_ID())); + + std::shared_ptr aStartA = aPointA1->pnt(); + std::shared_ptr aEndA = aPointA2->pnt(); + if (aStartA->distance(aEndA) < tolerance) + return false; + + myFlyoutUpdate = true; + double aX = (aStartA->x() + aEndA->x()) / 2.; + double aY = (aStartA->y() + aEndA->y()) / 2.; + + aFlyOutAttr->setValue(aX, aY); + myFlyoutUpdate = false; + + return true; +} + + +// =============== Auxiliary functions ================================== +std::shared_ptr intersect(FeaturePtr theLine1, FeaturePtr theLine2) +{ + // Start and end points of lines + std::shared_ptr aPointA1 = std::dynamic_pointer_cast( + theLine1->attribute(SketchPlugin_Line::START_ID())); + std::shared_ptr aPointA2 = std::dynamic_pointer_cast( + theLine1->attribute(SketchPlugin_Line::END_ID())); + + std::shared_ptr aPointB1 = std::dynamic_pointer_cast( + theLine2->attribute(SketchPlugin_Line::START_ID())); + std::shared_ptr aPointB2 = std::dynamic_pointer_cast( + theLine2->attribute(SketchPlugin_Line::END_ID())); + + std::shared_ptr aStartA = aPointA1->pnt(); + std::shared_ptr aEndA = aPointA2->pnt(); + std::shared_ptr aStartB = aPointB1->pnt(); + std::shared_ptr aEndB = aPointB2->pnt(); + if (aStartA->distance(aEndA) < tolerance || aStartB->distance(aEndB) < tolerance) + std::shared_ptr(); + + // Lines and their intersection point + std::shared_ptr aLA(new GeomAPI_Lin2d(aStartA, aEndA)); + std::shared_ptr aLB(new GeomAPI_Lin2d(aStartB, aEndB)); + return aLA->intersect(aLB); +}