X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintTangent.cpp;h=690587ae238e72030798244b7912f75e8331932d;hb=4f565b2204d3fba046aa8c851abada2a5a17bf6c;hp=37b59fab2b61808d8e48756d107d95e6ed857f90;hpb=4cbfb073803b0c753a8a31e677a5b786974cf983;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintTangent.cpp b/src/SketchSolver/SketchSolver_ConstraintTangent.cpp index 37b59fab2..690587ae2 100644 --- a/src/SketchSolver/SketchSolver_ConstraintTangent.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintTangent.cpp @@ -1,84 +1,141 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + #include -#include #include +#include + +#include +#include +#include -void SketchSolver_ConstraintTangent::process() + +/// \brief Check whether the entities has only one shared point +static bool hasSingleCoincidence(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2) { - cleanErrorMsg(); - if (!myBaseConstraint || !myStorage || myGroup == 0) { - /// TODO: Put error message here - return; + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + + const std::list& aPoints1 = theEntity1->subEntities(); + const std::list& aPoints2 = theEntity2->subEntities(); + + std::list::const_iterator aStartIt1 = aPoints1.begin(); + if (theEntity1->type() == ENTITY_ARC) ++aStartIt1; // skip center of arc + std::list::const_iterator aStartIt2 = aPoints2.begin(); + if (theEntity2->type() == ENTITY_ARC) ++aStartIt2; // skip center of arc + + int aNbCoinc = 0; + std::list::const_iterator anIt1, anIt2; + for (anIt1 = aStartIt1; anIt1 != aPoints1.end(); ++anIt1) { + if ((*anIt1)->type() != ENTITY_POINT) + continue; + std::shared_ptr aPt1 = aBuilder->point(*anIt1); + for (anIt2 = aStartIt2; anIt2 != aPoints2.end(); ++anIt2) { + if ((*anIt2)->type() != ENTITY_POINT) + continue; + std::shared_ptr aPt2 = aBuilder->point(*anIt2); + if (aPt1->distance(aPt2) < tolerance) + ++aNbCoinc; + } } - if (!mySlvsConstraints.empty()) // some data is changed, update constraint - update(myBaseConstraint); + return aNbCoinc == 1; +} + +/// \brief Check if two connected arcs have centers +/// in same direction relatively to connection point +static bool isInternalTangency(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2) +{ + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + return aBuilder->isArcArcTangencyInternal(theEntity1, theEntity2); +} - double aValue; - std::vector anEntID; - getAttributes(aValue, anEntID); - if (!myErrorMsg.empty()) + +void SketchSolver_ConstraintTangent::getAttributes( + double& theValue, + std::vector& theAttributes) +{ + SketchSolver_Constraint::getAttributes(theValue, theAttributes); + if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) { + theAttributes.clear(); return; + } + // Check the quantity of entities of each type and their order (arcs first) int aNbLines = 0; int aNbArcs = 0; - Slvs_Entity anEntities[2]; - myType = SLVS_C_CURVE_CURVE_TANGENT; - std::vector::iterator anEntIter = anEntID.begin(); - for (; anEntIter != anEntID.end(); anEntIter++) { - Slvs_Entity anEnt = myStorage->getEntity(*anEntIter); - if (anEnt.type == SLVS_E_LINE_SEGMENT) { - if (aNbLines == 0) - anEntities[1 + aNbLines] = anEnt; - aNbLines++; - myType = SLVS_C_ARC_LINE_TANGENT; + int aNbCircles = 0; + bool isSwap = false; // whether need to swap arguments (arc goes before line) + std::vector::iterator anEntIt = theAttributes.begin() + 2; + for (; anEntIt != theAttributes.end(); ++anEntIt) { + if ((*anEntIt)->type() == ENTITY_LINE) + ++aNbLines; + else if ((*anEntIt)->type() == ENTITY_ARC) { + ++aNbArcs; + isSwap = aNbLines > 0; } - else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) { - if (aNbArcs < 2) - anEntities[aNbArcs] = anEnt; - aNbArcs++; + else if ((*anEntIt)->type() == ENTITY_CIRCLE) { + ++aNbCircles; + isSwap = aNbLines > 0; } } - if (aNbLines + aNbArcs != 2) { - myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); - return; - } else if (aNbArcs < 1) { + if (aNbArcs < 1 && aNbCircles < 1) { myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE(); return; } - - // It is necessary to identify which points of entities are coincident - int aSlvsOtherFlag = 0; - int aSlvsOther2Flag = 0; - // Obtain start and end points of entities - Slvs_hEntity aPointsToFind[4]; - for (int i = 0; i < 2; i++) { - int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0; - aPointsToFind[2*i] = anEntities[i].point[aShift]; - aPointsToFind[2*i+1]= anEntities[i].point[aShift+1]; + if (aNbLines == 1) { + if (aNbArcs == 1) + myType = CONSTRAINT_TANGENT_ARC_LINE; + else if (aNbCircles == 1) + myType = CONSTRAINT_TANGENT_CIRCLE_LINE; + } + else if (aNbArcs == 2) { + myType = CONSTRAINT_TANGENT_ARC_ARC; + isArcArcInternal = isInternalTangency(theAttributes[2], theAttributes[3]); } - // Search coincident points - bool isPointFound = false; - for (int i = 0; i < 2 && !isPointFound; i++) - for (int j = 2; j < 4 && !isPointFound; j++) - if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) { - aSlvsOtherFlag = i; - aSlvsOther2Flag = j - 2; - isPointFound = true; - } - if (!isPointFound) { - // There is no coincident points between tangential objects. Generate error message - myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS(); + else { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); return; } - Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), - getType(), myGroup->getWorkplaneId(), aValue, - SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, anEntities[0].h, anEntities[1].h); - aConstraint.other = aSlvsOtherFlag; - aConstraint.other2 = aSlvsOther2Flag; - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - adjustConstraint(); + if (myType == CONSTRAINT_TANGENT_ARC_LINE && + !hasSingleCoincidence(theAttributes[2], theAttributes[3])) + myErrorMsg = SketchSolver_Error::TANGENCY_FAILED(); + + if (isSwap) { + EntityWrapperPtr aTemp = theAttributes[2]; + theAttributes[2] = theAttributes[3]; + theAttributes[3] = aTemp; + } } +void SketchSolver_ConstraintTangent::adjustConstraint() +{ + if (myType == CONSTRAINT_TANGENT_CIRCLE_LINE) { + ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front(); + AttributePtr aCircleCenter = aConstraint->entities().front()->baseAttribute(); + if (!aCircleCenter) + return; + FeaturePtr aCircle = ModelAPI_Feature::feature(aCircleCenter->owner()); + AttributeDoublePtr aRadius = std::dynamic_pointer_cast( + aCircle->attribute(SketchPlugin_Circle::RADIUS_ID())); + + if (fabs(aRadius->value()) == fabs(aConstraint->value())) + return; + + aConstraint->setValue(aRadius->value()); + + // Adjust the sign of constraint value + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + aBuilder->adjustConstraint(aConstraint); + myStorage->addConstraint(myBaseConstraint, aConstraint); + } + else if (myType == CONSTRAINT_TANGENT_ARC_ARC) { + ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front(); + if (isArcArcInternal != isInternalTangency( + aConstraint->entities().front(), aConstraint->entities().back())) { + // fully rebuld constraint, because it is unable to access attributes of PlaneGCS constraint + remove(); + process(); + } + } +}