X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Validators.cpp;h=73321550bff7b40a0f034d5f058ca717320961f6;hb=3b741a32c4706a6a78906aa6b12ef85628277037;hp=431cc0347c0c88618acda48017462a26eb90f91d;hpb=7e5d2154c4bc69712df0d02dc099d841b10d941d;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 431cc0347..73321550b 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -12,6 +12,7 @@ #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" @@ -19,6 +20,8 @@ #include "SketcherPrs_Tools.h" +#include + #include #include #include @@ -29,8 +32,12 @@ #include #include #include +#include #include +#include + +#include #include #include #include @@ -43,10 +50,11 @@ 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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -68,7 +76,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) { @@ -78,7 +86,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) { @@ -102,52 +110,18 @@ bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribut 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; + FeaturePtr aCoincidenceFeature = SketchPlugin_ConstraintCoincidence::findCoincidenceFeature + (theFeature1, theFeature2); + return aCoincidenceFeature.get() != NULL; } 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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -178,29 +152,33 @@ bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute if (aRefFea->getKind() == SketchPlugin_Line::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(); + 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()) { if (aOtherFea->getKind() != SketchPlugin_Line::ID() && aOtherFea->getKind() != SketchPlugin_Arc::ID()) { - theError = "It refers to an " + SketchPlugin_Arc::ID() + ", but " + aParamA + " is not a " - + SketchPlugin_Line::ID() + " or an " + SketchPlugin_Arc::ID(); + theError = "It refers to an %1, but %2 is not a %3 or an %4"; + theError.arg(SketchPlugin_Arc::ID()).arg(aParamA) + .arg(SketchPlugin_Line::ID()).arg(SketchPlugin_Arc::ID()); 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(); + theError = "It refers to an %1, but %2 is not a %3"; + theError.arg(SketchPlugin_Circle::ID()).arg(aParamA) + .arg(SketchPlugin_Line::ID()); return false; } } else { - theError = "It refers to " + aRefFea->getKind() + ", but should refer to " + SketchPlugin_Line::ID() - + " or " + SketchPlugin_Arc::ID() + " or " + SketchPlugin_Circle::ID(); + 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; @@ -215,10 +193,11 @@ bool SketchPlugin_TangentAttrValidator::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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -241,14 +220,16 @@ bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute, if (aRefAttr->object() == aRAttr->object()) { ObjectPtr anObject = aRefAttr->object(); std::string aName = anObject.get() ? anObject->data()->name() : ""; - theError = "The object " + aName + " has been already fixed."; + theError = "The object %1 has been already fixed."; + theError.arg(aName); return false; } } else if (aRefAttr->attr() == aRAttr->attr()) { AttributePtr anAttribute = aRefAttr->attr(); std::string aName = anAttribute.get() ? anAttribute->id() : ""; - theError = "The attribute " + aName + " has been already fixed."; + theError = "The attribute %1 has been already fixed."; + theError.arg(aName); return false; } } @@ -257,10 +238,11 @@ 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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -294,9 +276,9 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, 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(); + 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; } @@ -304,7 +286,8 @@ bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, 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."; + theError = "Feature with kinds %1 and %2 can not be equal."; + theError.arg(aType[0]).arg(aType[1]); return false; } return true; @@ -312,10 +295,11 @@ 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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -332,7 +316,8 @@ bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, std::list::iterator aMirIter = aMirroredObjects.begin(); for (; aMirIter != aMirroredObjects.end(); aMirIter++) if (aSelObject == *aMirIter) { - theError = "The object " + aName + " is a result of mirror"; + theError = "The object %1 is a result of mirror"; + theError.arg(aName); return false; } } @@ -341,10 +326,11 @@ bool SketchPlugin_MirrorAttrValidator::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 " + theAttribute->attributeType() + " type is not processed"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -356,7 +342,8 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttri FeaturePtr aConstraint = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttrA = aConstraint->data()->refattr(aParamA); if (!aRefAttrA) { - theError = "The " + aParamA + " attribute " + " should be " + ModelAPI_AttributeRefAttr::typeId(); + theError = "The %1 attribute should be %2"; + theError.arg(aParamA).arg(ModelAPI_AttributeRefAttr::typeId()); return false; } @@ -368,12 +355,14 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttri else { ObjectPtr anObject = aRefAttrA->object(); if (!anObject.get()) { - theError = aParamA + " attribute has an empty object"; + theError = "%1 attribute has an empty object"; + theError.arg(aParamA); return false; } FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrA->object()); if (!aFeature.get()) { - theError = aParamA + " attribute has an empty feature"; + theError = "%1 attribute has an empty feature"; + theError.arg(aParamA); return false; } @@ -387,7 +376,8 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttri else { FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrB->object()); if (!aFeature) { - theError = theAttribute->id() + " attribute has an empty object"; + theError = "%1 attribute has an empty object"; + theError.arg(theAttribute->id()); return false; } if (aFeature->getKind() == SketchPlugin_Point::ID()) @@ -400,10 +390,11 @@ 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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -431,7 +422,8 @@ bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, for (; anObjIter != aCopiedObjects.end(); anObjIter++) if (aSelObject == *anObjIter) { std::string aName = aSelObject.get() ? aSelObject->data()->name() : ""; - theError = "The object " + aName + " is a result of copy"; + theError = "The object %1 is a result of copy"; + theError.arg(aName); return false; } } @@ -440,7 +432,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()); @@ -457,9 +449,48 @@ 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 { std::shared_ptr aFilletFeature = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrListPtr aPointsRefList = std::dynamic_pointer_cast(theAttribute); @@ -493,6 +524,8 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut 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: @@ -582,14 +615,31 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut } if(aCoinsides.size() != 2) { - theError = ("Error: One of the selected points does not have two suitable edges for fillet."); + theError = "Error: One of the selected points does not have two suitable edges for fillet."; return false; } - // Check that lines not collinear + // 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(); @@ -613,10 +663,11 @@ bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribut bool SketchPlugin_MiddlePointAttrValidator::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"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } @@ -659,16 +710,18 @@ bool SketchPlugin_MiddlePointAttrValidator::isValid(const AttributePtr& theAttri bool SketchPlugin_ArcTangentPointValidator::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"; + 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 " + theAttribute->id() + " should be a point"; + theError = "The attribute %1 should be a point"; + theError.arg(theAttribute->id()); return false; } @@ -678,7 +731,8 @@ bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttri // 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"; + theError = "The attribute %1 is not supported"; + theError.arg(aPntId); return false; } } @@ -686,24 +740,40 @@ bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttri // 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"; + theError = "The attribute %1 is not supported"; + theError.arg(aPntId); return false; } } else { - theError = "Unable to build tangent arc on " + anAttrFeature->getKind(); + 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, - std::string& theError) const + Events_InfoMessage& theError) const { if (theAttribute->attributeType() != ModelAPI_AttributeSelection::typeId()) { - theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + theError = "The attribute with the %1 type is not processed"; + theError.arg(theAttribute->attributeType()); return false; } AttributeSelectionPtr aLineAttr = @@ -716,7 +786,8 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut } if (!anEdge || !anEdge->isLine()) { - theError = "The attribute " + theAttribute->id() + " should be a line"; + theError = "The attribute %1 should be a line"; + theError.arg(theAttribute->id()); return false; } @@ -743,3 +814,134 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut 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(); + 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()))); + + std::set > aPoints; + std::map, std::shared_ptr > aPointToAttributes; + ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(), + aX->dir(), aDirY, aPoints, aPointToAttributes); + + int aCoincidentToFeature = (int)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 && 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()); + 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; +}