X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Validators.cpp;h=8e85e516b552294decf451b9aec16d576a008977;hb=af69a9771accba3192bbb19edf77fb2dce428b7e;hp=b8b2fa53e498be217bd9f10fb550ea393caa5aca;hpb=4ca3fd41634c37f840d0cbb3f896fa97c2d3c457;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp old mode 100644 new mode 100755 index b8b2fa53e..8e85e516b --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -5,42 +5,65 @@ // Author: Vitaly SMETANNIKOV #include "SketchPlugin_Validators.h" -#include "SketchPlugin_ConstraintDistance.h" + +#include "SketchPlugin_Arc.h" +#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_Arc.h" -#include "SketchPlugin_Circle.h" #include "SketchPlugin_Point.h" +#include "SketchPlugin_Sketch.h" +#include "SketchPlugin_Tools.h" #include "SketcherPrs_Tools.h" +#include + #include #include #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, +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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + // 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(); AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; - bool isObject = aRefAttr->isObject(); if (!isObject) { // an attribute is a point. A point value is valid always for the distance @@ -49,86 +72,126 @@ bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribut // 1. check whether the references object is a linear ObjectPtr anObject = aRefAttr->object(); - const ModelAPI_AttributeValidator* aShapeValidator = - dynamic_cast(aFactory->validator("GeomValidators_ShapeType")); + const ModelAPI_AttributeValidator* aShapeValidator = + dynamic_cast( + aFactory->validator("GeomValidators_ShapeType")); std::list anArguments; anArguments.push_back("circle"); - bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments); + Events_InfoMessage aCircleError; + bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aCircleError); // the circle line is not a valid case - if (aShapeValid) + if (aShapeValid) { + theError = "Circle can not be used in distance constraint"; return false; - + } + anArguments.clear(); anArguments.push_back("line"); - aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments); + 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) - return true; - - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - // If it is a line then we have to check that first attribute id not a line - std::shared_ptr aSFeature = - std::dynamic_pointer_cast(theAttribute->owner()); - SketchPlugin_Sketch* aSketch = aSFeature->sketch(); - std::shared_ptr aPlane = SketchPlugin_Sketch::plane(aSketch); - std::shared_ptr aPoint = SketcherPrs_Tools::getFeaturePoint( - aFeature->data(), aParamA, aPlane); - if (aPoint) - return true; + if (aShapeValid) { + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + // If it is a line then we have to check that first attribute id not a line + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(theAttribute->owner()); + SketchPlugin_Sketch* aSketch = aSFeature->sketch(); + std::shared_ptr aPlane = SketchPlugin_Sketch::plane(aSketch); + std::shared_ptr aPoint = SketcherPrs_Tools::getFeaturePoint( + aFeature->data(), aParamA, aPlane); + if (!aPoint.get()) { + theError = "One of parameters of distance constraint should be a point"; + return false; + } + } } - return false; + return true; } -bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute, +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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + // 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(); - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; + FeaturePtr anAttributeFeature = + std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(theAttribute); bool isObject = aRefAttr->isObject(); ObjectPtr anObject = aRefAttr->object(); - if (isObject && anObject) { + if (isObject && anObject.get()) { FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject); - AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA); + AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA); ObjectPtr aOtherObject = aOtherAttr->object(); FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject); + if (!aOtherFea) + return true; if (aRefFea->getKind() == SketchPlugin_Line::ID()) { - if (aOtherFea->getKind() != SketchPlugin_Arc::ID()) + if (aOtherFea->getKind() != SketchPlugin_Arc::ID() && + aOtherFea->getKind() != SketchPlugin_Circle::ID()) { + theError = "It refers to a %1, but %2 is neither an %3 nor %4"; + theError.arg(SketchPlugin_Line::ID()).arg(aParamA) + .arg(SketchPlugin_Arc::ID()).arg(SketchPlugin_Circle::ID()); return false; - } else if (aRefFea->getKind() == SketchPlugin_Arc::ID()) { + } + } + else if (aRefFea->getKind() == SketchPlugin_Arc::ID() || + aRefFea->getKind() == SketchPlugin_Circle::ID()) { if (aOtherFea->getKind() != SketchPlugin_Line::ID() && - aOtherFea->getKind() != SketchPlugin_Arc::ID()) + aOtherFea->getKind() != SketchPlugin_Arc::ID() && + aOtherFea->getKind() != SketchPlugin_Circle::ID()) { + theError = "It refers to an %1, but %2 is not a %3 or an %4 or a %5"; + theError.arg(SketchPlugin_Arc::ID()).arg(aParamA) + .arg(SketchPlugin_Line::ID()).arg(SketchPlugin_Arc::ID()) + .arg(SketchPlugin_Circle::ID()); return false; - } else + } + } + else { + theError = "It refers to %1, but should refer to %2 or %3 or %4"; + theError.arg(aRefFea->getKind()).arg(SketchPlugin_Line::ID()) + .arg(SketchPlugin_Arc::ID()).arg(SketchPlugin_Circle::ID()); return false; - + } return true; } - return false; + else { + theError = "It uses an empty object"; + return false; + } + + 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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + std::shared_ptr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); if (!aFeature) return true; AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; SketchPlugin_Sketch* aSketch = aFeature->sketch(); int aNbFeatures = aSketch->numberOfSubs(); @@ -139,88 +202,123 @@ bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute, AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast( aSubFeature->attribute(SketchPlugin_ConstraintRigid::ENTITY_A())); if (aRefAttr->isObject()) { - if (aRefAttr->object() == aRAttr->object()) + if (aRefAttr->object() == aRAttr->object()) { + ObjectPtr anObject = aRefAttr->object(); + std::string aName = anObject.get() ? anObject->data()->name() : ""; + theError = "The object %1 has been already fixed."; + theError.arg(aName); return false; - } else if (aRefAttr->attr() == aRAttr->attr()) + } + } + else if (aRefAttr->attr() == aRAttr->attr()) { + AttributePtr anAttribute = aRefAttr->attr(); + std::string aName = anAttribute.get() ? anAttribute->id() : ""; + theError = "The attribute %1 has been already fixed."; + theError.arg(aName); return false; + } } return true; } -bool SketchPlugin_EqualAttrValidator::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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + std::string aParamA = theArguments.front(); FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttr[2]; aRefAttr[0] = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; aRefAttr[1] = aFeature->data()->refattr(aParamA); - if (!aRefAttr[0]->isObject() || !aRefAttr[1]->isObject()) + if (!aRefAttr[0]->isObject() || !aRefAttr[1]->isObject()) { + theError = "Attributes can not be used in equal constraint"; 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(); - aFeature = ModelAPI_Feature::feature(anObject); - if (!aFeature) + if (!anObject.get()) { + theError = "An empty object is used."; return false; - - if (aFeature->getKind() == SketchPlugin_Line::ID()) { - aType[i] = 1; - continue; } - if (aFeature->getKind() == SketchPlugin_Circle::ID()) { - aType[i] = 2; - continue; + + aFeature = ModelAPI_Feature::feature(anObject); + if (!aFeature.get()) { + theError = "An empty feature is used."; + return false; } - 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 %1 feature kind of attribute is wrong. It should be %2 or %3 or %4"; + theError.arg(aFeature->getKind()).arg(SketchPlugin_Line::ID()) + .arg(SketchPlugin_Circle::ID()).arg(SketchPlugin_Arc::ID()); + // wrong type of attribute + return false; } - // wrong type of attribute - return false; } - if ((aType[0] == 1 && aType[1] == 2) || - (aType[0] == 2 && aType[1] == 1)) + if ((aType[0] == SketchPlugin_Line::ID() || aType[1] == SketchPlugin_Line::ID()) && + aType[0] != aType[1]) { + theError = "Feature with kinds %1 and %2 can not be equal."; + theError.arg(aType[0]).arg(aType[1]); return false; + } return true; } -bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, +bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - AttributeSelectionListPtr aSelAttr = - std::dynamic_pointer_cast(theAttribute); - if (!aSelAttr) + if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) { + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; + } + + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefListPtr aSelAttr = std::dynamic_pointer_cast(theAttribute); AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast( aFeature->attribute(SketchPlugin_Constraint::ENTITY_C())); std::list aMirroredObjects = aRefListOfMirrored->list(); for(int anInd = 0; anInd < aSelAttr->size(); anInd++) { - std::shared_ptr aSelect = aSelAttr->value(anInd); + ObjectPtr aSelObject = aSelAttr->object(anInd); + std::string aName = aSelObject.get() ? aSelObject->data()->name() : ""; std::list::iterator aMirIter = aMirroredObjects.begin(); for (; aMirIter != aMirroredObjects.end(); aMirIter++) - if (aSelect->context() == *aMirIter) + if (aSelObject == *aMirIter) { + theError = "The object %1 is a result of mirror"; + theError.arg(aName); return false; + } } return true; } - -bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttribute, +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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + // 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(); @@ -228,20 +326,32 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttri FeaturePtr aConstraint = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttrA = aConstraint->data()->refattr(aParamA); - if (!aRefAttrA) + if (!aRefAttrA) { + theError = "The %1 attribute should be %2"; + theError.arg(aParamA).arg(ModelAPI_AttributeRefAttr::typeId()); return false; + } - AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttrB) - return false; + AttributeRefAttrPtr aRefAttrB = + std::dynamic_pointer_cast(theAttribute); // first attribute is a point, it may coincide with any object if (!aRefAttrA->isObject()) return true; else { + ObjectPtr anObject = aRefAttrA->object(); + if (!anObject.get()) { + theError = "%1 attribute has an empty object"; + theError.arg(aParamA); + return false; + } FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrA->object()); - if (!aFeature) + if (!aFeature.get()) { + theError = "%1 attribute has an empty feature"; + theError.arg(aParamA); return false; + } + if (aFeature->getKind() == SketchPlugin_Point::ID()) return true; } @@ -251,25 +361,32 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttri return true; else { FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrB->object()); - if (!aFeature) + if (!aFeature) { + theError = "%1 attribute has an empty object"; + theError.arg(theAttribute->id()); return false; + } if (aFeature->getKind() == SketchPlugin_Point::ID()) return true; } - + theError = "There is no an attribute filled by a point"; return false; } -bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, +bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, const std::list& theArguments, - std::string& theError) const + Events_InfoMessage& theError) const { - FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - AttributeSelectionListPtr aSelAttr = - std::dynamic_pointer_cast(theAttribute); - if (!aSelAttr) + if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) { + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; + } + + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeRefListPtr aSelAttr = + std::dynamic_pointer_cast(theAttribute); AttributeRefListPtr aRefListOfInitial = std::dynamic_pointer_cast( aFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); @@ -280,18 +397,586 @@ bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, std::list::iterator anObjIter; for(int anInd = 0; anInd < aSelAttr->size(); anInd++) { - std::shared_ptr aSelect = aSelAttr->value(anInd); + ObjectPtr aSelObject = aSelAttr->object(anInd); anObjIter = anInitialObjects.begin(); for (; anObjIter != anInitialObjects.end(); anObjIter++) - if (aSelect->context() == *anObjIter) + if (aSelObject == *anObjIter) break; if (anObjIter != anInitialObjects.end()) continue; anObjIter = aCopiedObjects.begin(); for (; anObjIter != aCopiedObjects.end(); anObjIter++) - if (aSelect->context() == *anObjIter) + if (aSelObject == *anObjIter) { + std::string aName = aSelObject.get() ? aSelObject->data()->name() : ""; + theError = "The object %1 is a result of copy"; + theError.arg(aName); return false; + } } return true; } +bool SketchPlugin_SolverErrorValidator::isValid( + const std::shared_ptr& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeStringPtr aAttributeString = theFeature->string(SketchPlugin_Sketch::SOLVER_ERROR()); + + if (!aAttributeString->value().empty()) { + theError = aAttributeString->value(); + return false; + } + + return true; +} + +bool SketchPlugin_SolverErrorValidator::isNotObligatory(std::string theFeature, + std::string theAttribute) +{ + 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, + Events_InfoMessage& theError) const +{ + 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; + } + + 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())); + } + } + } + + 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 selected point not on the one of the fillet result edge. + if(aSetOfPointsOnResultEdges.find(aPointAttribute) != aSetOfPointsOnResultEdges.end()) { + return false; + } + } + + // 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(!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 = + fabs((aFirstEndPnt->x() - aFirstStartPnt->x()) * + (aSecondStartPnt->y() - aFirstStartPnt->y()) - + (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y())); + double aCheck2 = + fabs((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; + } + } + } + + 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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + + // 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(); + + 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; + } + } + + 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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); + AttributePtr anAttr = aRefAttr->attr(); + if (!anAttr) { + theError = "The attribute %1 should be a point"; + theError.arg(theAttribute->id()); + 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 %1 is not supported"; + theError.arg(aPntId); + 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 %1 is not supported"; + theError.arg(aPntId); + return false; + } + } + else { + theError = "Unable to build tangent arc on %1"; + theError.arg(anAttrFeature->getKind()); + return false; + } + + // 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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + 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 %1 should be a line"; + theError.arg(theAttribute->id()); + 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_SplitValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + bool aValid = false; + + if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) { + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return aValid; + } + AttributeReferencePtr aFeatureAttr = + std::dynamic_pointer_cast(theAttribute); + + ObjectPtr anAttrObject = aFeatureAttr->value(); + FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttrObject); + if (!anAttrFeature) + return aValid; + + std::string aKind = anAttrFeature->getKind(); + if (aKind == SketchPlugin_Line::ID() || + aKind == SketchPlugin_Arc::ID() || + aKind == SketchPlugin_Circle::ID()) { + + std::set anEdgeShapes; + ModelAPI_Tools::shapesOfType(anAttrFeature, GeomAPI_Shape::EDGE, anEdgeShapes); + if (anEdgeShapes.empty() || anEdgeShapes.size() > 1 /*there case has not existed yet*/) + return aValid; + + // coincidences to the feature + std::set > aRefAttributes; + ModelGeomAlgo_Point2D::getPointsOfReference(anAttrFeature, + SketchPlugin_ConstraintCoincidence::ID(), + aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID()); + + GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape(); + std::shared_ptr aSFeature = + std::dynamic_pointer_cast(anAttrFeature); + SketchPlugin_Sketch* aSketch = aSFeature->sketch(); + + std::shared_ptr aData = aSketch->data(); + std::shared_ptr aC = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + std::shared_ptr aX = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::DIRX_ID())); + std::shared_ptr aNorm = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); + + typedef std::map, + std::pair >, + std::list > > > PointToRefsMap; + PointToRefsMap aPointsInfo; + + //std::list > aPoints; + //std::map, std::shared_ptr > + // aPointToAttributes; + //std::map, + // std::list< std::shared_ptr > > aPointToAttributes; + ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(), + aX->dir(), aDirY, aPointsInfo);//aPoints, aPointToAttributes); + + int aCoincidentToFeature = (int)aPointsInfo.size();//aPoints.size(); + if (aKind == SketchPlugin_Circle::ID()) + aValid = aCoincidentToFeature >= 2; + else + aValid = aCoincidentToFeature >= 1; + } + + return aValid; +} + +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 %1 type is not processed"; + theError.arg(theAttribute->attributeType()); + return false; + } + + AttributeSelectionPtr aFeatureAttr = + std::dynamic_pointer_cast(theAttribute); + std::shared_ptr anEdge; + if (aFeatureAttr.get()) { + GeomShapePtr aVal = aFeatureAttr->value(); + ResultPtr aRes = aFeatureAttr->context(); + if(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 %1 should be an edge"; + theError.arg(theAttribute->id()); + 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()); + bool aValid = (fabs(aDot) >= tolerance && fabs(aDot) < 1.0 - tolerance) || + (fabs(aDot) < tolerance && fabs(aDist) > tolerance); + if (!aValid) + theError = "Error: Edge is already in the sketch plane."; + return aValid; + } + 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()); + bool aValid = fabs(aDot - 1.0) < tolerance * tolerance && fabs(aDist) > tolerance; + if (!aValid) + theError.arg(anEdge->isCircle() ? "Error: Cirlce is already in the sketch plane." + : "Error: Arc is already in the sketch plane."); + return aValid; + } + + theError = "Error: Selected object is not line, circle or arc."; + return false; +}