X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_Validators.cpp;h=b446bab1642528b4922b8ce7e84956f677309445;hb=417aaae9c4c335cad27eaf82458d8c09bb263cc6;hp=38bf03582b9d0a1bd9299078d981e3ef1414b3e9;hpb=324e003dfdc5e343baa124722c8a944df0276571;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_Validators.cpp b/src/PartSet/PartSet_Validators.cpp old mode 100644 new mode 100755 index 38bf03582..b446bab16 --- a/src/PartSet/PartSet_Validators.cpp +++ b/src/PartSet/PartSet_Validators.cpp @@ -6,23 +6,31 @@ #include "PartSet_Validators.h" +#include "PartSet_Tools.h" +#include "PartSet_SketcherMgr.h" + #include #include #include #include #include -#include #include #include +#include #include #include #include #include +#include #include #include +#include #include +#include +#include +#include #include #ifdef _DEBUG @@ -31,7 +39,9 @@ int shapesNbPoints(const ModuleBase_ISelection* theSelection) { - QList aList = theSelection->getSelected(); + QList aList = theSelection->getSelected(ModuleBase_ISelection::Viewer); + ModuleBase_ISelection::filterSelectionOnEqualPoints(aList); + int aCount = 0; foreach (ModuleBase_ViewerPrs aPrs, aList) { const TopoDS_Shape& aShape = aPrs.shape(); @@ -45,7 +55,7 @@ int shapesNbPoints(const ModuleBase_ISelection* theSelection) int shapesNbLines(const ModuleBase_ISelection* theSelection) { - QList aList = theSelection->getSelected(); + QList aList = theSelection->getSelected(ModuleBase_ISelection::Viewer); int aCount = 0; foreach(ModuleBase_ViewerPrs aPrs, aList) { const TopoDS_Shape& aShape = aPrs.shape(); @@ -63,206 +73,442 @@ int shapesNbLines(const ModuleBase_ISelection* theSelection) return aCount; } -bool PartSet_DistanceValidator::isValid(const ModuleBase_ISelection* theSelection) const + +std::shared_ptr sketcherPlane(ModuleBase_Operation* theOperation) { - int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection); - return (aCount > 0) && (aCount < 3); + std::shared_ptr aEmptyPln; + if (theOperation) { + ModuleBase_OperationFeature* aFeatureOp = dynamic_cast(theOperation); + if (aFeatureOp) { + CompositeFeaturePtr aFeature = + std::dynamic_pointer_cast(aFeatureOp->feature()); + if (aFeature && (aFeature->getKind() == SketchPlugin_Sketch::ID())) + return PartSet_Tools::sketchPlane(aFeature); + } + } + return aEmptyPln; } -bool PartSet_LengthValidator::isValid(const ModuleBase_ISelection* theSelection) const + +bool isEmptySelectionValid(ModuleBase_Operation* theOperation) { - int aCount = shapesNbLines(theSelection); - return (aCount > 0) && (aCount < 2); + ModuleBase_OperationFeature* aFeatureOp = dynamic_cast(theOperation); + // during the create operation empty selection is always valid + if (!aFeatureOp->isEditOperation()) { + return true; + } + else { + if (PartSet_SketcherMgr::isSketchOperation(aFeatureOp)) { + std::shared_ptr aPlane = sketcherPlane(theOperation); + if (aPlane.get()) + return true; + else + return false; + } + else// in edit operation an empty selection is always valid, performed for re-entrant operrations + return true; + } } -bool PartSet_PerpendicularValidator::isValid(const ModuleBase_ISelection* theSelection) const +bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const { - int aCount = shapesNbLines(theSelection); - return (aCount > 0) && (aCount < 3); + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection); + return (aCount > 0) && (aCount < 3); + } } -bool PartSet_ParallelValidator::isValid(const ModuleBase_ISelection* theSelection) const +bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const { - int aCount = shapesNbLines(theSelection); - return (aCount > 0) && (aCount < 3); + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbLines(theSelection); + return (aCount == 1); + } } -bool PartSet_RadiusValidator::isValid(const ModuleBase_ISelection* theSelection) const +bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const { - QList aList = theSelection->getSelected(); - ModuleBase_ViewerPrs aPrs; - int aCount = 0; - foreach (ModuleBase_ViewerPrs aPrs, aList) { - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull()) { - if (aShape.ShapeType() == TopAbs_EDGE) { - TopoDS_Edge aEdge = TopoDS::Edge(aShape); - Standard_Real aStart, aEnd; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd); - GeomAdaptor_Curve aAdaptor(aCurve); - if (aAdaptor.GetType() == GeomAbs_Circle) - aCount++; + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbLines(theSelection); + return (aCount > 0) && (aCount < 3); + } +} + +bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbLines(theSelection); + return (aCount > 0) && (aCount < 3); + } +} + +bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + QList aList = theSelection->getSelected(ModuleBase_ISelection::Viewer); + ModuleBase_ViewerPrs aPrs; + int aCount = 0; + foreach (ModuleBase_ViewerPrs aPrs, aList) { + const TopoDS_Shape& aShape = aPrs.shape(); + if (!aShape.IsNull()) { + if (aShape.ShapeType() == TopAbs_EDGE) { + TopoDS_Edge aEdge = TopoDS::Edge(aShape); + Standard_Real aStart, aEnd; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd); + GeomAdaptor_Curve aAdaptor(aCurve); + if (aAdaptor.GetType() == GeomAbs_Circle) + aCount++; + } } } + return (aCount == 1); + } +} + +bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + QList aList = theSelection->getSelected(ModuleBase_ISelection::Viewer); + return (aList.count() == 1); + } +} + + +bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + // Coincident can be applied to points and to lines + int aCount = shapesNbPoints(theSelection); + aCount += shapesNbLines(theSelection); + return (aCount > 0) && (aCount < 3); + } +} + +bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbLines(theSelection); + return (aCount == 1); + } +} + +bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbPoints(theSelection); + return aCount == 1; + } +} + +bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + QList aList = theSelection->getSelected(ModuleBase_ISelection::Viewer); + if ((aList.size() == 0) || (aList.size() > 2)) + return false; + + ModuleBase_ViewerPrs aPrs = aList.first(); + const TopoDS_Shape& aShape = aPrs.shape(); + if (aShape.IsNull()) + return false; + + if (aShape.ShapeType() != TopAbs_EDGE) + return false; + + std::shared_ptr aShapePtr(new GeomAPI_Shape); + aShapePtr->setImpl(new TopoDS_Shape(aShape)); + GeomAPI_Edge aEdge1(aShapePtr); + + if (aEdge1.isLine() || aEdge1.isArc()) { + if (aList.size() == 2) { + // Check second selection + aPrs = aList.last(); + const TopoDS_Shape& aShape2 = aPrs.shape(); + if (aShape2.IsNull()) + return false; + + if (aShape2.ShapeType() != TopAbs_EDGE) + return false; + + std::shared_ptr aShapePtr2(new GeomAPI_Shape); + aShapePtr2->setImpl(new TopoDS_Shape(aShape2)); + GeomAPI_Edge aEdge2(aShapePtr2); + if (aEdge1.isLine() && aEdge2.isArc()) + return true; + else if (aEdge1.isArc() && aEdge2.isLine()) + return true; + else + return false; + } else + return true; + } + return false; + } +} + +bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + int aCount = shapesNbLines(theSelection); + return (aCount > 0) && (aCount < 3); + } +} + +bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const +{ + if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) { + return isEmptySelectionValid(theOperation); + } else { + QList aList = theSelection->getSelected(ModuleBase_ISelection::Viewer); + ModuleBase_ViewerPrs aPrs; + int aCount = 0; + int aType = 0; + foreach (ModuleBase_ViewerPrs aPrs, aList) { + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aPrs.shape())); + if (aShape->isEdge()) { + aCount++; + GeomAPI_Edge aEdge(aShape); + if (aEdge.isLine()) { + if (aCount == 1) + aType = 1; + else if (aType != 1) + return false; + } else if (aEdge.isCircle()) { + if (aCount == 1) + aType = 2; + else if (aType != 2) + return false; + } else if (aEdge.isArc()) { + if (aCount == 1) + aType = 3; + else if (aType != 3) + return false; + } + } else + return false; + } + return (aCount > 0) && (aCount < 3); } - return (aCount > 0) && (aCount < 2); } -bool PartSet_RigidValidator::isValid(const ModuleBase_ISelection* theSelection) const + +std::string PartSet_DifferentObjectsValidator::errorMessage( + const PartSet_DifferentObjectsValidator::ErrorType& theType, + const std::string& thEqualObject, const std::string& theFirstAttribute, + const std::string& theSecondAttribute) const { - int aCount = shapesNbLines(theSelection); - return (aCount > 0) && (aCount < 2); + std::string anError; + switch (theType) { + case EqualObjects: + anError = "The feature uses one " + thEqualObject + " object in " + + theFirstAttribute + " and " + theSecondAttribute + " attributes."; + break; + case EqualAttributes: + anError = "The feature uses reference to one " + thEqualObject + " attribute in " + + theFirstAttribute + " and " + theSecondAttribute + " attributes."; + break; + case EqualShapes: + anError = "The feature uses one shape in " + + theFirstAttribute + " and " + theSecondAttribute + " attributes."; + break; + case EmptyShapes: + anError = "The feature uses empty shapes in " + + theFirstAttribute + " and " + theSecondAttribute + " attributes."; + break; + break; + default: + break; + } + return anError; } bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, - const std::list& theArguments) const + const std::list& theArguments, + std::string& theError) const { FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); - // 1. check whether the object of the attribute is not among the feature attributes - // find the attribute's object - ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute); - - // check whether the object is not among other feature attributes - if (anObject.get() != NULL) { - // Check RefAttr attributes - std::list > anAttrs = aFeature->data()->attributes(""); - //if (anAttrs.size() > 0) { - std::list >::iterator anIt = anAttrs.begin(); - for(; anIt != anAttrs.end(); anIt++) { - AttributePtr anAttr = *anIt; - // the function parameter attribute should be skipped - if (anAttr.get() == NULL || anAttr->id() == theAttribute->id()) - continue; - ObjectPtr aCurObject = GeomValidators_Tools::getObject(anAttr); - if (aCurObject && aCurObject == anObject) - return false; + // the type of validated attributes should be equal, attributes with different types are not validated + // Check RefAttr attributes + std::string anAttrType = theAttribute->attributeType(); + std::list > anAttrs; + + if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) { + AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast(theAttribute); + bool isObject = anAttr->isObject(); + ObjectPtr anObject = anAttr->object(); + AttributePtr anAttributeAttr = anAttr->attr(); + + anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + if (anAttrs.size() > 0) { + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) { + if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); + if (aRef->isObject() != isObject) + continue; + if (isObject) { + if (aRef->object() == anObject) { + theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "", + theAttribute->id(), aRef->id()); + return false; + } + } + else { // the attribute reference + if (aRef->attr() == anAttributeAttr) { + theError = errorMessage(EqualAttributes, + anAttributeAttr.get() ? anAttributeAttr->id() : "", + theAttribute->id(), aRef->id()); + return false; + } + } + } + } } } - else { - // 2. collect object referenced by theAttribute and ... - if (featureHasReferences(theAttribute)) { - // 3. check whether the attribute value is not among other feature attributes - std::list > anAttrs = - aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + else if (anAttrType == ModelAPI_AttributeSelection::typeId()) { + AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); + ResultPtr aContext = anAttr->context(); + GeomShapePtr aShape = anAttr->value(); + + // Check selection attributes + anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId()); + if (anAttrs.size() > 0) { + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) { + if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); + // check the object is already presented + if (aRef->context() == aContext) { + bool aHasShape = aShape.get() != NULL; + if (!aHasShape || aRef->value()->isEqual(aShape)) { + theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id()); + return false; + } + } + } + } + } + } + else if (anAttrType == ModelAPI_AttributeReference::typeId()) { + AttributeReferencePtr anAttr = std::dynamic_pointer_cast(theAttribute); + ObjectPtr anObject = anAttr->value(); + // Check selection attributes + anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId()); + if (anAttrs.size() > 0) { std::list >::iterator anAttr = anAttrs.begin(); for(; anAttr != anAttrs.end(); anAttr++) { - if (*anAttr) { - std::shared_ptr aRef = - std::dynamic_pointer_cast(*anAttr); + if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) { + std::shared_ptr aRef = + std::dynamic_pointer_cast(*anAttr); // check the object is already presented - if (!aRef->isObject() && aRef->attr() == theAttribute) + if (aRef->value() == anObject) { + theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "", + theAttribute->id(), aRef->id()); return false; + } } -// TODO(nds) v1.0.2 master -//bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, -// const std::list& theArguments, -// const ObjectPtr& theObject, -// const GeomShapePtr& theShape) const -//{ -// // Check RefAttr attributes -// std::list > anAttrs = -// theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); -// if (anAttrs.size() > 0) { -// std::list >::iterator anAttr = anAttrs.begin(); -// for(; anAttr != anAttrs.end(); anAttr++) { -// if (*anAttr) { -// std::shared_ptr aRef = -// std::dynamic_pointer_cast(*anAttr); -// // check the object is already presented -// if (aRef->isObject() && aRef->object() == theObject) -// return false; -// } -// } -// } -// // Check selection attributes -// anAttrs = theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId()); -// if (anAttrs.size() > 0) { -// std::list >::iterator anAttr = anAttrs.begin(); -// for(; anAttr != anAttrs.end(); anAttr++) { -// if (*anAttr) { -// std::shared_ptr aRef = -// std::dynamic_pointer_cast(*anAttr); -// // check the object is already presented -// if (aRef->isInitialized() && aRef->context() == theObject) { -// if (theShape.get() != NULL) { -// if (aRef->value()->isEqual(theShape)) -// return false; -// } else -// return false; -// } -// } -// } -// } -// // Check selection attributes -// anAttrs = theFeature->data()->attributes(ModelAPI_AttributeReference::typeId()); -// if (anAttrs.size() > 0) { -// std::list >::iterator anAttr = anAttrs.begin(); -// for(; anAttr != anAttrs.end(); anAttr++) { -// if (*anAttr) { -// std::shared_ptr aRef = -// std::dynamic_pointer_cast(*anAttr); -// // check the object is already presented -// if (aRef->isInitialized() && aRef->value() == theObject) -// return false; -// ======= end of todo + return true; } - return true; } } - return true; -} - -bool PartSet_DifferentObjectsValidator::featureHasReferences(const AttributePtr& theAttribute) const -// TODO(nds) v1.0.2 master -//bool PartSet_DifferentObjectsValidator::isValid(const FeaturePtr& theFeature, -// const std::list& theArguments, -// const AttributePtr& theAttribute) const -//{ -// if (PartSet_DifferentObjectsValidator::isValid(theAttribute, theArguments)) { -// std::list > anAttrs = -// theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); -// std::list >::iterator anAttr = anAttrs.begin(); -// for(; anAttr != anAttrs.end(); anAttr++) { -// if (*anAttr) { -// std::shared_ptr aRef = -// std::dynamic_pointer_cast(*anAttr); -// // check the object is already presented -// if (!aRef->isObject() && aRef->attr() == theAttribute) -// return false; -// } -// } -// return true; -// } -// return false; -//} -// -//bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, -// const std::list& theArguments) const -// ======= end of todo -{ - std::list > > allRefs; - if (theAttribute->owner().get() && theAttribute->owner()->data().get()) - theAttribute->owner()->data()->referencesToObjects(allRefs); - // collect object referenced by theAttribute - std::list* anAttrObjs = 0; - std::list > >::iterator aRefIter = allRefs.begin(); - for(; aRefIter != allRefs.end(); aRefIter++) { - if (theAttribute->id() == aRefIter->first) - anAttrObjs = &(aRefIter->second); + else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) { + std::shared_ptr aCurSelList = + std::dynamic_pointer_cast(theAttribute); + anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId()); + if(anAttrs.size() > 0) { + std::list>::iterator anAttrItr = anAttrs.begin(); + for(; anAttrItr != anAttrs.end(); anAttrItr++){ + if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){ + std::shared_ptr aRefSelList = + std::dynamic_pointer_cast(*anAttrItr); + for(int i = 0; i < aCurSelList->size(); i++) { + std::shared_ptr aCurSel = aCurSelList->value(i); + ResultPtr aCurSelContext = aCurSel->context(); + ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext); + std::shared_ptr aCurSelCompSolid; + if(aCurSelCompSolidPtr.get()) { + aCurSelCompSolid = aCurSelCompSolidPtr->shape(); + } + for(int j = 0; j < aRefSelList->size(); j++) { + std::shared_ptr aRefSel = aRefSelList->value(j); + ResultPtr aRefSelContext = aRefSel->context(); + ResultCompSolidPtr aRefSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aRefSelContext); + std::shared_ptr aRefSelCompSolid; + if(aRefSelCompSolidPtr.get()) { + aRefSelCompSolid = aRefSelCompSolidPtr->shape(); + } + if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value())) + || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) { + theError = errorMessage(EqualShapes, "", theAttribute->id(), + aRefSel->id()); + return false; + } + if(aCurSelContext == aRefSelContext) { + if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) { + theError = errorMessage(EmptyShapes, "", theAttribute->id(), + aRefSel->id()); + return false; + } + if (aCurSel->value()->isEqual(aRefSel->value())) { + theError = errorMessage(EqualShapes, "", theAttribute->id(), + aRefSel->id()); + return false; + } + } + } + } + } + } + } } - if (!anAttrObjs || anAttrObjs->empty()) - return true; // theAttribute does not references to anything - // check with all others - for(aRefIter = allRefs.begin(); aRefIter != allRefs.end(); aRefIter++) { - if (theAttribute->id() == aRefIter->first) - continue; // do not check with myself - std::list::iterator aReferenced = aRefIter->second.begin(); - for(; aReferenced != aRefIter->second.end(); aReferenced++) { - std::list::iterator aReferencedByMe = anAttrObjs->begin(); - for(; aReferencedByMe != anAttrObjs->end(); aReferencedByMe++) { - if (*aReferenced == *aReferencedByMe) // found same objects! - return false; + else if (anAttrType == ModelAPI_AttributeRefList::typeId()) { + std::shared_ptr aCurSelList = + std::dynamic_pointer_cast(theAttribute); + anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId()); + if (anAttrs.size() > 0) { + std::list>::iterator anAttrItr = anAttrs.begin(); + for (; anAttrItr != anAttrs.end(); anAttrItr++){ + if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){ + std::shared_ptr aRefSelList = + std::dynamic_pointer_cast(*anAttrItr); + for (int i = 0; i < aCurSelList->size(); i++) { + ObjectPtr aCurSelObject = aCurSelList->object(i); + for (int j = 0; j < aRefSelList->size(); j++) { + if (aCurSelObject == aRefSelList->object(j)) { + theError = errorMessage(EqualObjects, + aCurSelObject.get() ? aCurSelObject->data()->name() : "", + theAttribute->id(), aCurSelList->id()); + return false; + } + } + } + } } } } @@ -270,30 +516,73 @@ bool PartSet_DifferentObjectsValidator::featureHasReferences(const AttributePtr& } bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute, - const std::list& theArguments) const + const std::list& theArguments, + std::string& theError) const { bool isSketchEntities = true; std::set anEntityKinds; + std::string anEntityKindsStr; std::list::const_iterator anIt = theArguments.begin(), aLast = theArguments.end(); for (; anIt != aLast; anIt++) { anEntityKinds.insert(*anIt); + if (!anEntityKindsStr.empty()) + anEntityKindsStr += ", "; + anEntityKindsStr += *anIt; } std::string anAttributeType = theAttribute->attributeType(); if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { AttributeSelectionListPtr aSelectionListAttr = std::dynamic_pointer_cast(theAttribute); - // it filters only selection list attributes - std::string aType = aSelectionListAttr->selectionType().c_str(); // all context objects should be sketch entities - int aSize = aSelectionListAttr->size(); - for (int i = 0; i < aSelectionListAttr->size() && isSketchEntities; i++) { + for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize && isSketchEntities; i++) { AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i); ObjectPtr anObject = aSelectAttr->context(); + // a context of the selection attribute is a feature result. It can be a case when the result + // of the feature is null, e.g. the feature is modified and has not been executed yet. + // The validator returns an invalid result here. The case is an extrusion built on a sketch + // feature. A new sketch element creation leads to an empty result. + if (!anObject.get()) + isSketchEntities = false; + else { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); + } + } + } + if (anAttributeType == ModelAPI_AttributeSelection::typeId()) { + AttributeSelectionPtr aSelectAttr = + std::dynamic_pointer_cast(theAttribute); + ObjectPtr anObject = aSelectAttr->context(); + // a context of the selection attribute is a feature result. It can be a case when the result + // of the feature is null, e.g. the feature is modified and has not been executed yet. + // The validator returns an invalid result here. The case is an extrusion built on a sketch + // feature. A new sketch element creation leads to an empty result. + if (!anObject.get()) + isSketchEntities = false; + else { FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); } } + if (anAttributeType == ModelAPI_AttributeRefList::typeId()) { + AttributeRefListPtr aRefListAttr = + std::dynamic_pointer_cast(theAttribute); + // all context objects should be sketch entities + for (int i = 0, aSize = aRefListAttr->size(); i < aSize && isSketchEntities; i++) { + ObjectPtr anObject = aRefListAttr->object(i); + // a context of the selection attribute is a feature result. It can be a case when the result + // of the feature is null, e.g. the feature is modified and has not been executed yet. + // The validator returns an invalid result here. The case is an extrusion built on a sketch + // feature. A new sketch element creation leads to an empty result. + if (!anObject.get()) + isSketchEntities = false; + else { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end(); + } + } + } if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) { std::shared_ptr aRef = std::dynamic_pointer_cast(theAttribute); @@ -307,15 +596,22 @@ bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute, } } } + if (!isSketchEntities) { + theError = "It refers to feature, which kind is not in the list: " + anEntityKindsStr; + } return isSketchEntities; } - - -bool PartSet_SameTypeAttrValidator::isValid( - const AttributePtr& theAttribute, const std::list& theArguments ) const +bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { + if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) { + theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed"; + 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(); @@ -323,19 +619,50 @@ bool PartSet_SameTypeAttrValidator::isValid( FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(theAttribute); - if (!aRefAttr) - return false; + QList aCoinsideLines; bool isObject = aRefAttr->isObject(); ObjectPtr anObject = aRefAttr->object(); if (isObject && anObject) { FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject); - AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA); ObjectPtr aOtherObject = aOtherAttr->object(); + // if the other attribute is not filled still, the result is true + if (!aOtherObject.get()) + return true; FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject); - return aRefFea->getKind() == aOtherFea->getKind(); + + // check that both have coincidence + FeaturePtr aConstrFeature; + std::set aCoinList; + const std::set>& aRefsList = aRefFea->data()->refsToMe(); + std::set>::const_iterator aIt; + for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) { + std::shared_ptr aAttr = (*aIt); + aConstrFeature = std::dynamic_pointer_cast(aAttr->owner()); + if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { + AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast(aAttr); + AttributePtr aAR = aRAttr->attr(); + if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc + aCoinList.insert(aConstrFeature); + PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, + SketchPlugin_ConstraintCoincidence::ENTITY_A()); + PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, + SketchPlugin_ConstraintCoincidence::ENTITY_B()); + } + } + // if there is no coincidence then it is not valid + if (aCoinList.size() > 0) { + QList::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end(); + bool aValid = false; + for (; anIt != aLast && !aValid; anIt++) { + aValid = *anIt == aOtherFea; + } + if (aValid) + return true; + } } + theError = "There is no a common coincident point."; return false; }