X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSketchPlugin%2FSketchPlugin_Validators.cpp;h=93152b1cb18ce8fe8493b39e53a95f480cbaef92;hb=64981a525f8bc2c450475822e96dcc2766454ad3;hp=3b79ad68cae45a90022ea0093a0bb4cddb89c0af;hpb=459678da22b6316c58e0e0e769f04776bdf24997;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 3b79ad68c..93152b1cb 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -10,7 +10,9 @@ #include "SketchPlugin_Circle.h" #include "SketchPlugin_ConstraintCoincidence.h" #include "SketchPlugin_ConstraintDistance.h" +#include "SketchPlugin_ConstraintFillet.h" #include "SketchPlugin_ConstraintRigid.h" +#include "SketchPlugin_ConstraintTangent.h" #include "SketchPlugin_Line.h" #include "SketchPlugin_Point.h" #include "SketchPlugin_Sketch.h" @@ -18,22 +20,34 @@ #include "SketcherPrs_Tools.h" +#include + #include #include #include #include + +#include #include #include #include #include +#include +#include +#include +#include +#include #include +#include +#include + const double tolerance = 1.e-7; bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -58,7 +72,7 @@ bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribut dynamic_cast(aFactory->validator("GeomValidators_ShapeType")); std::list anArguments; anArguments.push_back("circle"); - std::string aCircleError; + Events_InfoMessage aCircleError; bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aCircleError); // the circle line is not a valid case if (aShapeValid) { @@ -68,7 +82,7 @@ bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribut anArguments.clear(); anArguments.push_back("line"); - std::string aLineError; + Events_InfoMessage aLineError; aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aLineError); // if the attribute value is not a line, that means it is a vertex. A vertex is always valid if (aShapeValid) { @@ -89,9 +103,52 @@ bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribut return true; } + +static bool hasCoincidentPoint(FeaturePtr theFeature1, FeaturePtr theFeature2) +{ + FeaturePtr aConstrFeature; + std::list anAttrList; + if (theFeature1->getKind() == SketchPlugin_Circle::ID() || + theFeature2->getKind() == SketchPlugin_Circle::ID()) + return false; + if (theFeature2->getKind() == SketchPlugin_Line::ID()) { + anAttrList.push_back(theFeature2->attribute(SketchPlugin_Line::START_ID())); + anAttrList.push_back(theFeature2->attribute(SketchPlugin_Line::END_ID())); + } else if (theFeature2->getKind() == SketchPlugin_Arc::ID()) { + anAttrList.push_back(theFeature2->attribute(SketchPlugin_Arc::START_ID())); + anAttrList.push_back(theFeature2->attribute(SketchPlugin_Arc::END_ID())); + } + + const std::set& aRefsList = theFeature1->data()->refsToMe(); + std::set::const_iterator aRefIt = aRefsList.begin(); + for (; aRefIt != aRefsList.end(); ++aRefIt) { + aConstrFeature = std::dynamic_pointer_cast((*aRefIt)->owner()); + if (aConstrFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + continue; + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*aRefIt); + AttributePtr anAttr = aRefAttr->attr(); + if (anAttr->id() == SketchPlugin_Arc::CENTER_ID()) + continue; + + anAttr = aConstrFeature->attribute(SketchPlugin_Constraint::ENTITY_A()); + if (anAttr == *aRefIt) + anAttr = aConstrFeature->attribute(SketchPlugin_Constraint::ENTITY_B()); + + aRefAttr = std::dynamic_pointer_cast(anAttr); + if (!aRefAttr) + continue; + anAttr = aRefAttr->attr(); + for (std::list::const_iterator anIt = anAttrList.begin(); + anIt != anAttrList.end(); ++anIt) + if (*anIt == anAttr) + return true; + } + return false; +} + bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -114,11 +171,19 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA); ObjectPtr aOtherObject = aOtherAttr->object(); FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject); + if (!aOtherFea) + return true; + + if ((aRefFea->getKind() == SketchPlugin_Arc::ID() || + aOtherFea->getKind() == SketchPlugin_Arc::ID()) && + !hasCoincidentPoint(aRefFea, aOtherFea)) + return false; if (aRefFea->getKind() == SketchPlugin_Line::ID()) { - if (aOtherFea->getKind() != SketchPlugin_Arc::ID()) { - theError = "It refers to a " + SketchPlugin_Line::ID() + ", but " + aParamA + " is not an " - + SketchPlugin_Arc::ID(); + if (aOtherFea->getKind() != SketchPlugin_Arc::ID() && + aOtherFea->getKind() != SketchPlugin_Circle::ID()) { + theError = "It refers to a " + SketchPlugin_Line::ID() + ", but " + aParamA + " is neither an " + + SketchPlugin_Arc::ID() + " nor " + SketchPlugin_Circle::ID(); return false; } } @@ -130,9 +195,16 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute return false; } } + else if (aRefFea->getKind() == SketchPlugin_Circle::ID()) { + if (aOtherFea->getKind() != SketchPlugin_Line::ID()) { + theError = "It refers to an " + SketchPlugin_Circle::ID() + ", but " + aParamA + " is not a " + + SketchPlugin_Line::ID(); + return false; + } + } else { - theError = "It refers to " + aRefFea->getKind() + "but should refer to " + SketchPlugin_Line::ID() - + " or " + SketchPlugin_Arc::ID(); + theError = "It refers to " + aRefFea->getKind() + ", but should refer to " + SketchPlugin_Line::ID() + + " or " + SketchPlugin_Arc::ID() + " or " + SketchPlugin_Circle::ID(); return false; } return true; @@ -145,9 +217,9 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute return true; } -bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute, +bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -189,7 +261,7 @@ bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute, bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -207,7 +279,7 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, return false; } - int aType[2] = {0, 0}; // types of attributes: 0 - incorrect, 1 - line, 2 - circle, 3 - arc + std::string aType[2]; std::list anArguments; for (int i = 0; i < 2; i++) { ObjectPtr anObject = aRefAttr[i]->object(); @@ -222,29 +294,21 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, return false; } - if (aFeature->getKind() == SketchPlugin_Line::ID()) { - aType[i] = 1; - continue; - } - if (aFeature->getKind() == SketchPlugin_Circle::ID()) { - aType[i] = 2; - continue; - } - if (aFeature->getKind() == SketchPlugin_Arc::ID()) { - aType[i] = 3; - continue; + aType[i] = aFeature->getKind(); + if (aFeature->getKind() != SketchPlugin_Line::ID() && + aFeature->getKind() != SketchPlugin_Circle::ID() && + aFeature->getKind() != SketchPlugin_Arc::ID()) { + theError = "The " + aFeature->getKind() + " feature kind of attribute is wrong. It should be " + + SketchPlugin_Line::ID() + " or " + SketchPlugin_Circle::ID() + " or " + + SketchPlugin_Arc::ID(); + // wrong type of attribute + return false; } - theError = "The " + aFeature->getKind() + " feature kind of attribute is wrong. It should be " + - SketchPlugin_Line::ID() + " or " + SketchPlugin_Circle::ID() + " or " + - SketchPlugin_Arc::ID(); - // wrong type of attribute - return false; } - if ((aType[0] == 1 && aType[1] == 2) || - (aType[0] == 2 && aType[1] == 1)) { - theError = "Feature with kinds " + SketchPlugin_Line::ID() + " and " + - SketchPlugin_Circle::ID() + "can not be equal."; + if ((aType[0] == SketchPlugin_Line::ID() || aType[1] == SketchPlugin_Line::ID()) && + aType[0] != aType[1]) { + theError = "Feature with kinds " + aType[0] + " and " + aType[1] + "can not be equal."; return false; } return true; @@ -252,7 +316,7 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -279,10 +343,9 @@ bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, return true; } - bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -341,7 +404,7 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttri bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) { theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; @@ -381,7 +444,7 @@ bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, bool SketchPlugin_SolverErrorValidator::isValid(const std::shared_ptr& theFeature, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { AttributeStringPtr aAttributeString = theFeature->string(SketchPlugin_Sketch::SOLVER_ERROR()); @@ -398,165 +461,426 @@ bool SketchPlugin_SolverErrorValidator::isNotObligatory(std::string theFeature, return true; } +static bool hasSameTangentFeature(const std::set& theRefsList, const FeaturePtr theFeature) +{ + for(std::set::const_iterator anIt = theRefsList.cbegin(); anIt != theRefsList.cend(); ++anIt) { + std::shared_ptr aAttr = (*anIt); + FeaturePtr aFeature = std::dynamic_pointer_cast(aAttr->owner()); + if (aFeature->getKind() == SketchPlugin_ConstraintTangent::ID()) { + AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_ConstraintTangent::ENTITY_A())); + AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_ConstraintTangent::ENTITY_B())); + if(anAttrRefA.get()) { + ResultPtr aResA = std::dynamic_pointer_cast(anAttrRefA->object()); + if(aResA.get()) { + DocumentPtr aDoc = aResA->document(); + if(aDoc.get()) { + FeaturePtr aFeatureA = aDoc->feature(aResA); + if(aFeatureA.get() && aFeatureA == theFeature) { + return true; + } + } + } + } + if(anAttrRefB.get()) { + ResultPtr aResB = std::dynamic_pointer_cast(anAttrRefB->object()); + if(aResB.get()) { + DocumentPtr aDoc = aResB->document(); + if(aDoc.get()) { + FeaturePtr aFeatureB = aDoc->feature(aResB); + if(aFeatureB.get() && aFeatureB == theFeature) { + return true; + } + } + } + } + } + } + return false; +} + bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { - if(!theAttribute.get()) { + std::shared_ptr aFilletFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefAttrListPtr aPointsRefList = std::dynamic_pointer_cast(theAttribute); + if(aPointsRefList->size() == 0) { + theError = "Error: List of points is empty."; return false; } - AttributeRefAttrPtr aBase = std::dynamic_pointer_cast(theAttribute); - AttributePtr anAttrBase = aBase->attr(); - if(aBase->isObject()) { - return false; + std::map aPointsFeaturesMap = aFilletFeature->pointsFeaturesMap(); + std::set aSetOfPointsOnResultEdges; + for(std::map::iterator aPointsIter = aPointsFeaturesMap.begin(); + aPointsIter != aPointsFeaturesMap.end(); + ++aPointsIter) { + const SketchPlugin_ConstraintFillet::FilletFeatures& aFeatures = aPointsIter->second; + const std::list& aResultEdges = aFeatures.resultEdges; + for(std::list::const_iterator aResultIter = aResultEdges.cbegin(); + aResultIter != aResultEdges.cend(); + ++aResultIter) { + FeaturePtr aResultFeature = *aResultIter; + if(aResultFeature->getKind() == SketchPlugin_Line::ID()) { + aSetOfPointsOnResultEdges.insert(aResultFeature->attribute(SketchPlugin_Line::START_ID())); + aSetOfPointsOnResultEdges.insert(aResultFeature->attribute(SketchPlugin_Line::END_ID())); + } else if(aResultFeature->getKind() == SketchPlugin_Arc::ID()) { + aSetOfPointsOnResultEdges.insert(aResultFeature->attribute(SketchPlugin_Arc::START_ID())); + aSetOfPointsOnResultEdges.insert(aResultFeature->attribute(SketchPlugin_Arc::END_ID())); + } + } } - // If we alredy have some result then: - // - if it is the same point all ok - // - if it is point on the fillet arc then it is not valid - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - AttributePtr aBaseLinesAttribute = aFeature->attribute(SketchPlugin_Constraint::ENTITY_C()); - AttributeRefListPtr aRefListOfBaseLines = std::dynamic_pointer_cast(aBaseLinesAttribute); - std::list anOldFeatList = aRefListOfBaseLines->list(); - if(!aRefListOfBaseLines->list().empty()) { - FeaturePtr anOldFeatureA, anOldFeatureB; - std::list::iterator aFeatIt = anOldFeatList.begin(); - anOldFeatureA = ModelAPI_Feature::feature(*aFeatIt++); - anOldFeatureB = ModelAPI_Feature::feature(*aFeatIt); - - AttributePtr anAttrStartA = - anOldFeatureA->attribute(anOldFeatureA->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::START_ID() : SketchPlugin_Arc::START_ID()); - AttributePtr anAttrEndA = - anOldFeatureA->attribute(anOldFeatureA->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::END_ID() : SketchPlugin_Arc::END_ID()); - AttributePtr anAttrStartB = - anOldFeatureB->attribute(anOldFeatureB->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::START_ID() : SketchPlugin_Arc::START_ID()); - AttributePtr anAttrEndB = - anOldFeatureB->attribute(anOldFeatureB->getKind() == SketchPlugin_Line::ID() ? SketchPlugin_Line::END_ID() : SketchPlugin_Arc::END_ID()); - - std::shared_ptr aBasePnt = std::dynamic_pointer_cast(anAttrBase)->pnt(); - std::shared_ptr aStartPntA = std::dynamic_pointer_cast(anAttrStartA)->pnt(); - std::shared_ptr anEndPntA = std::dynamic_pointer_cast(anAttrEndA)->pnt(); - std::shared_ptr aStartPntB = std::dynamic_pointer_cast(anAttrStartB)->pnt(); - std::shared_ptr anEndPntB = std::dynamic_pointer_cast(anAttrEndB)->pnt(); - double aDistBaseStartA = aBasePnt->distance(aStartPntA); - double aDistBaseEndA = aBasePnt->distance(anEndPntA); - double aDistStartAStartB = aStartPntA->distance(aStartPntB); - double aDistStartAEndB = aStartPntA->distance(anEndPntB); - double aDistEndAStartB = anEndPntA->distance(aStartPntB); - double aDistEndAEndB = anEndPntA->distance(anEndPntB); - - if((aDistBaseStartA < tolerance && (aDistStartAStartB < tolerance || aDistStartAEndB < tolerance)) || - (aDistBaseEndA < tolerance && (aDistEndAStartB < tolerance || aDistEndAStartB < tolerance))) { - return true; - } + std::list> aPointsList = aPointsRefList->list(); + for(std::list>::const_iterator aPointsIt = aPointsList.cbegin(); aPointsIt != aPointsList.cend(); aPointsIt++) { + ObjectPtr anObject = (*aPointsIt).first; + AttributePtr aPointAttribute = (*aPointsIt).second; + if (!aPointAttribute.get()) + return false; + std::shared_ptr aSelectedPnt = std::dynamic_pointer_cast(aPointAttribute)->pnt(); + + // If we alredy have some result then: + // - if it is the same point all ok, just skip it + // - if it is point on the fillet result edge then it is not valid + if(!aPointsFeaturesMap.empty()) { + if(aPointsFeaturesMap.find(aPointAttribute) != aPointsFeaturesMap.end()) { + continue; + } - // Check that point not on fillet arc - AttributeRefListPtr aRefListOfFillet = std::dynamic_pointer_cast( - aFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); - std::list aNewFeatList = aRefListOfFillet->list(); - if(!aNewFeatList.empty()) { - aFeatIt = aNewFeatList.begin(); - FeaturePtr aNewArc; - //aNewFeatureA = ModelAPI_Feature::feature(*aFeatIt++); - //aNewFeatureB = ModelAPI_Feature::feature(*aFeatIt++); - aFeatIt++; aFeatIt++; - aNewArc = ModelAPI_Feature::feature(*aFeatIt); - AttributePtr anArcStart = aNewArc->attribute(SketchPlugin_Arc::START_ID()); - AttributePtr anArcEnd = aNewArc->attribute(SketchPlugin_Arc::END_ID()); - std::shared_ptr anArcStartPnt = std::dynamic_pointer_cast(anArcStart)->pnt(); - std::shared_ptr anArcEndPnt = std::dynamic_pointer_cast(anArcEnd)->pnt(); - double aDistBaseArcStart = aBasePnt->distance(anArcStartPnt); - double aDistBaseArcEnd = aBasePnt->distance(anArcEndPnt); - if(aDistBaseArcStart < tolerance || aDistBaseArcEnd < tolerance) { + // Check that selected point not on the one of the fillet result edge. + if(aSetOfPointsOnResultEdges.find(aPointAttribute) != aSetOfPointsOnResultEdges.end()) { return false; } } - } - const std::set& aRefsList = anAttrBase->owner()->data()->refsToMe(); - std::set::const_iterator aIt; - FeaturePtr aCoincident; - for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { - std::shared_ptr aAttr = (*aIt); - FeaturePtr aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); - if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { - AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast( - aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A())); - AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast( - aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B())); - if(anAttrRefA.get() && !anAttrRefA->isObject()) { - AttributePtr anAttrA = anAttrRefA->attr(); - if(anAttrBase == anAttrA) { - aCoincident = aConstrFeature; - break; + // Obtain constraint coincidence for the fillet point. + const std::set& aRefsList = aPointAttribute->owner()->data()->refsToMe(); + FeaturePtr aConstraintCoincidence; + for(std::set::const_iterator anIt = aRefsList.cbegin(); anIt != aRefsList.cend(); ++anIt) { + std::shared_ptr aAttr = (*anIt); + FeaturePtr aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); + if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { + AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast( + aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A())); + AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast( + aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B())); + if(anAttrRefA.get() && !anAttrRefA->isObject()) { + AttributePtr anAttrA = anAttrRefA->attr(); + if(aPointAttribute == anAttrA) { + aConstraintCoincidence = aConstrFeature; + break; + } + } + if(anAttrRefB.get() && !anAttrRefB->isObject()) { + AttributePtr anAttrB = anAttrRefB->attr(); + if(aPointAttribute == anAttrB) { + aConstraintCoincidence = aConstrFeature; + break; + } } } - if(anAttrRefA.get() && !anAttrRefB->isObject()) { - AttributePtr anAttrB = anAttrRefB->attr(); - if(anAttrBase == anAttrB) { - aCoincident = aConstrFeature; - break; + } + + if(!aConstraintCoincidence.get()) { + theError = "Error: one of the selected point does not have coicidence."; + return false; + } + + // Get coincides from constraint. + std::set aCoinsides; + SketchPlugin_Tools::findCoincidences(aConstraintCoincidence, + SketchPlugin_ConstraintCoincidence::ENTITY_A(), + aCoinsides); + SketchPlugin_Tools::findCoincidences(aConstraintCoincidence, + SketchPlugin_ConstraintCoincidence::ENTITY_B(), + aCoinsides); + + // Remove points from set of coincides. + std::set aNewSetOfCoincides; + for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { + if((*anIt)->getKind() != SketchPlugin_Line::ID() && + (*anIt)->getKind() != SketchPlugin_Arc::ID()) { + continue; + } + if((*anIt)->getKind() == SketchPlugin_Arc::ID()) { + AttributePtr anArcCenter = (*anIt)->attribute(SketchPlugin_Arc::CENTER_ID()); + std::shared_ptr anArcCenterPnt = std::dynamic_pointer_cast(anArcCenter)->pnt(); + double aDistSelectedArcCenter = aSelectedPnt->distance(anArcCenterPnt); + if(aDistSelectedArcCenter < tolerance) { + continue; + } + } + aNewSetOfCoincides.insert(*anIt); + } + aCoinsides = aNewSetOfCoincides; + + // If we still have more than two coincides remove auxilary entities from set of coincides. + if(aCoinsides.size() > 2) { + aNewSetOfCoincides.clear(); + for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { + if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) { + aNewSetOfCoincides.insert(*anIt); } } + aCoinsides = aNewSetOfCoincides; + } + + if(aCoinsides.size() != 2) { + theError = "Error: One of the selected points does not have two suitable edges for fillet."; + return false; + } + + // Check that selected edges don't have tangent constraint. + std::set::iterator anIt = aCoinsides.begin(); + FeaturePtr aFirstFeature = *anIt++; + FeaturePtr aSecondFeature = *anIt; + const std::set& aFirstFeatureRefsList = aFirstFeature->data()->refsToMe(); + if(hasSameTangentFeature(aFirstFeatureRefsList, aSecondFeature)) { + theError = "Error: Edges in selected point has tangent constraint."; + return false; + } + + std::list aFirstResults = aFirstFeature->results(); + for(std::list::iterator aResIt = aFirstResults.begin(); aResIt != aFirstResults.end(); ++aResIt) { + ResultPtr aRes = *aResIt; + const std::set& aResRefsList = aRes->data()->refsToMe(); + if(hasSameTangentFeature(aResRefsList, aSecondFeature)) { + theError = "Error: Edges in selected point has tangent constraint."; + return false; + } + } + + // Check that lines not collinear + if(aFirstFeature->getKind() == SketchPlugin_Line::ID() && aSecondFeature->getKind() == SketchPlugin_Line::ID()) { + std::string aStartAttr = SketchPlugin_Line::START_ID(); + std::string anEndAttr = SketchPlugin_Line::END_ID(); + std::shared_ptr aFirstStartPnt, aFirstEndPnt, aSecondStartPnt, aSecondEndPnt; + aFirstStartPnt = std::dynamic_pointer_cast(aFirstFeature->attribute(aStartAttr))->pnt(); + aFirstEndPnt = std::dynamic_pointer_cast(aFirstFeature->attribute(anEndAttr))->pnt(); + aSecondStartPnt = std::dynamic_pointer_cast(aSecondFeature->attribute(aStartAttr))->pnt(); + aSecondEndPnt = std::dynamic_pointer_cast(aSecondFeature->attribute(anEndAttr))->pnt(); + double aCheck1 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondStartPnt->y() - aFirstStartPnt->y()) - + (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); + double aCheck2 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondEndPnt->y() - aFirstStartPnt->y()) - + (aSecondEndPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); + if(aCheck1 < 1.e-7 && aCheck2 < 1.e-7) { + return false; + } } } - if(!aCoincident.get()) { + return true; +} + +bool SketchPlugin_MiddlePointAttrValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; return false; } - std::set aCoinsides; - SketchPlugin_Tools::findCoincidences(aCoincident, - SketchPlugin_ConstraintCoincidence::ENTITY_A(), - aCoinsides); - SketchPlugin_Tools::findCoincidences(aCoincident, - SketchPlugin_ConstraintCoincidence::ENTITY_B(), - aCoinsides); - // Remove points - std::set aNewLines; - for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { - if((*anIt)->getKind() != SketchPlugin_Point::ID()) { - aNewLines.insert(*anIt); - } - } - aCoinsides = aNewLines; + // there is a check whether the feature contains a point and a linear edge or two point values + std::string aParamA = theArguments.front(); + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - // Remove auxilary lines - if(aCoinsides.size() > 2) { - aNewLines.clear(); - for(std::set::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) { - if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) { - aNewLines.insert(*anIt); + FeaturePtr anAttributeFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + AttributeRefAttrPtr anOtherAttr = anAttributeFeature->data()->refattr(aParamA); + + AttributeRefAttrPtr aRefAttrs[2] = {aRefAttr, anOtherAttr}; + int aNbPoints = 0; + int aNbLines = 0; + for (int i = 0; i < 2; ++i) { + if (!aRefAttrs[i]->isObject()) + ++aNbPoints; + else { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrs[i]->object()); + if (!aFeature) { + if (aNbPoints + aNbLines != 0) + return true; + else continue; } + + if (aFeature->getKind() == SketchPlugin_Point::ID()) + ++aNbPoints; + else if (aFeature->getKind() == SketchPlugin_Line::ID()) + ++aNbLines; } - aCoinsides = aNewLines; } - if(aCoinsides.size() != 2) { + if (aNbPoints != 1 || aNbLines != 1) { + theError = "Middle point constraint allows points and lines only"; + return false; + } + return true; +} + +bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttribute, + const std::list& /*theArguments*/, + Events_InfoMessage& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + AttributePtr anAttr = aRefAttr->attr(); + if (!anAttr) { + theError = "The attribute " + theAttribute->id() + " should be a point"; + return false; + } + + FeaturePtr anAttrFeature = std::dynamic_pointer_cast(anAttr->owner()); + const std::string& aFeatureType = anAttrFeature->getKind(); + if (aFeatureType == SketchPlugin_Arc::ID()) { + // selected point should not be a center of arc + const std::string& aPntId = anAttr->id(); + if (aPntId != SketchPlugin_Arc::START_ID() && aPntId != SketchPlugin_Arc::END_ID()) { + theError = "The attribute " + aPntId + " is not supported"; + return false; + } + } + else if (aFeatureType == SketchPlugin_Line::ID()) { + // selected point should be bound point of line + const std::string& aPntId = anAttr->id(); + if (aPntId != SketchPlugin_Line::START_ID() && aPntId != SketchPlugin_Line::END_ID()) { + theError = "The attribute " + aPntId + " is not supported"; + return false; + } + } + else { + theError = "Unable to build tangent arc on " + anAttrFeature->getKind(); return false; } - // Check that lines not collinear - std::set::iterator anIt = aCoinsides.begin(); - FeaturePtr aFirstFeature = *anIt++; - FeaturePtr aSecondFeature = *anIt; - if(aFirstFeature->getKind() == SketchPlugin_Line::ID() && aSecondFeature->getKind() == SketchPlugin_Line::ID()) { - std::string aStartAttr = SketchPlugin_Line::START_ID(); - std::string anEndAttr = SketchPlugin_Line::END_ID(); - std::shared_ptr aFirstStartPnt, aFirstEndPnt, aSecondStartPnt, aSecondEndPnt; - aFirstStartPnt = std::dynamic_pointer_cast(aFirstFeature->attribute(aStartAttr))->pnt(); - aFirstEndPnt = std::dynamic_pointer_cast(aFirstFeature->attribute(anEndAttr))->pnt(); - aSecondStartPnt = std::dynamic_pointer_cast(aSecondFeature->attribute(aStartAttr))->pnt(); - aSecondEndPnt = std::dynamic_pointer_cast(aSecondFeature->attribute(anEndAttr))->pnt(); - double aCheck1 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondStartPnt->y() - aFirstStartPnt->y()) - - (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); - double aCheck2 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondEndPnt->y() - aFirstStartPnt->y()) - - (aSecondEndPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); - if(aCheck1 < 1.e-7 && aCheck2 < 1.e-7) { + // Check the tangent point is equal to arc end + FeaturePtr anArc = std::dynamic_pointer_cast(aRefAttr->owner()); + std::shared_ptr anEndPoint = std::dynamic_pointer_cast( + anArc->attribute(SketchPlugin_Arc::END_ID())); + if (anEndPoint->isInitialized()) { + std::shared_ptr aTangPt = + std::dynamic_pointer_cast(anAttr); + if (aTangPt->pnt()->distance(anEndPoint->pnt()) < tolerance) { + theError = "Unable to build arc on same points"; return false; } } return true; } + +bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeSelection::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + AttributeSelectionPtr aLineAttr = + std::dynamic_pointer_cast(theAttribute); + std::shared_ptr anEdge; + if(aLineAttr && aLineAttr->value() && aLineAttr->value()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(aLineAttr->value())); + } else if(aLineAttr->context() && aLineAttr->context()->shape() && aLineAttr->context()->shape()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(aLineAttr->context()->shape())); + } + + if (!anEdge || !anEdge->isLine()) { + theError = "The attribute " + theAttribute->id() + " should be a line"; + return false; + } + + std::shared_ptr aLineDir = anEdge->line()->direction(); + + // find a sketch + std::shared_ptr aSketch; + std::set aRefs = aLineAttr->owner()->data()->refsToMe(); + std::set::const_iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) { + CompositeFeaturePtr aComp = + std::dynamic_pointer_cast((*anIt)->owner()); + if (aComp && aComp->getKind() == SketchPlugin_Sketch::ID()) { + aSketch = std::dynamic_pointer_cast(aComp); + break; + } + } + if (!aSketch) { + theError = "There is no sketch referring to the current feature"; + return false; + } + + std::shared_ptr aPlane = aSketch->plane(); + std::shared_ptr aNormal = aPlane->direction(); + return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance; +} + +bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theAttribute->attributeType() != ModelAPI_AttributeSelection::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + return false; + } + + AttributeSelectionPtr aFeatureAttr = + std::dynamic_pointer_cast(theAttribute); + std::shared_ptr anEdge; + if(aFeatureAttr && aFeatureAttr->value() && aFeatureAttr->value()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(aFeatureAttr->value())); + } else if(aFeatureAttr->context() && aFeatureAttr->context()->shape() && + aFeatureAttr->context()->shape()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(aFeatureAttr->context()->shape())); + } + + if (!anEdge) { + theError = "The attribute " + theAttribute->id() + " should be an edge"; + return false; + } + + // find a sketch + std::shared_ptr aSketch; + std::set aRefs = theAttribute->owner()->data()->refsToMe(); + std::set::const_iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) { + CompositeFeaturePtr aComp = + std::dynamic_pointer_cast((*anIt)->owner()); + if (aComp && aComp->getKind() == SketchPlugin_Sketch::ID()) { + aSketch = std::dynamic_pointer_cast(aComp); + break; + } + } + if (!aSketch) { + theError = "There is no sketch referring to the current feature"; + return false; + } + + std::shared_ptr aPlane = aSketch->plane(); + std::shared_ptr aNormal = aPlane->direction(); + std::shared_ptr anOrigin = aPlane->location(); + + if (anEdge->isLine()) { + std::shared_ptr aLine = anEdge->line(); + std::shared_ptr aLineDir = aLine->direction(); + std::shared_ptr aLineLoc = aLine->location(); + double aDot = aNormal->dot(aLineDir); + double aDist = aLineLoc->xyz()->decreased(anOrigin->xyz())->dot(aNormal->xyz()); + return (fabs(aDot) >= tolerance && fabs(aDot) < 1.0 - tolerance) || + (fabs(aDot) < tolerance && fabs(aDist) > tolerance); + } + else if (anEdge->isCircle() || anEdge->isArc()) { + std::shared_ptr aCircle = anEdge->circle(); + std::shared_ptr aCircNormal = aCircle->normal(); + std::shared_ptr aCircCenter = aCircle->center(); + double aDot = fabs(aNormal->dot(aCircNormal)); + double aDist = aCircCenter->xyz()->decreased(anOrigin->xyz())->dot(aNormal->xyz()); + return fabs(aDot - 1.0) < tolerance * tolerance && fabs(aDist) > tolerance; + } + + return false; +}