Salome HOME
Log desktop actions
[modules/shaper.git] / src / PartSet / PartSet_Validators.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 9b4aa47..40b1932
@@ -1,8 +1,21 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:        PartSet_Validators.cpp
-// Created:     09 July 2014
-// Author:      Vitaly SMETANNIKOV
+// Copyright (C) 2014-2023  CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include "PartSet_Validators.h"
 
 #include <ModuleBase_ISelection.h>
 #include <ModuleBase_WidgetShapeSelector.h>
 #include <ModuleBase_OperationFeature.h>
+#include <ModuleBase_ViewerPrs.h>
+
+#include <GeomDataAPI_Point2D.h>
+#include <GeomAPI_Pnt2d.h>
+
+#include <Events_InfoMessage.h>
 
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_Object.h>
+#include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
 
 #include <SketchPlugin_Sketch.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Point.h>
 #include <GeomAPI_Edge.h>
 
+#include <Locale_Convert.h>
+
 #include <list>
+#include <unordered_map>
 #ifdef _DEBUG
 #include <iostream>
 #endif
 
 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
 {
-  QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
+  QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
   ModuleBase_ISelection::filterSelectionOnEqualPoints(aList);
 
   int aCount = 0;
-  foreach (ModuleBase_ViewerPrs aPrs, aList) {
-    const TopoDS_Shape& aShape = aPrs.shape();
-    if (!aShape.IsNull()) {
-      if (aShape.ShapeType() == TopAbs_VERTEX)
+  foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
+    const GeomShapePtr& aShape = aPrs->shape();
+    if (aShape.get() && !aShape->isNull()) {
+      if (aShape->shapeType() == GeomAPI_Shape::VERTEX)
         aCount++;
     }
   }
   return aCount;
 }
 
-int shapesNbLines(const ModuleBase_ISelection* theSelection)
+typedef std::unordered_map<int, int> ShapeQuantity;
+
+int shapesNbEdges(const ModuleBase_ISelection* theSelection, ShapeQuantity& theEdges)
 {
-  QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
+  QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
   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);
+  foreach(ModuleBase_ViewerPrsPtr aPrs, aList) {
+    const GeomShapePtr& aShape = aPrs->shape();
+    if (aShape.get() && !aShape->isNull()) {
+      if (aShape->shapeType() == GeomAPI_Shape::EDGE) {
+        const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
+        TopoDS_Edge aEdge = TopoDS::Edge(aTDShape);
         Standard_Real aStart, aEnd;
         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
         GeomAdaptor_Curve aAdaptor(aCurve);
-        if (aAdaptor.GetType() == GeomAbs_Line)
-          aCount++;
+        theEdges[(int)aAdaptor.GetType()] += 1;
+        aCount++;
       }
     }
   }
@@ -78,21 +105,23 @@ std::shared_ptr<GeomAPI_Pln> sketcherPlane(ModuleBase_Operation* theOperation)
 {
   std::shared_ptr<GeomAPI_Pln> aEmptyPln;
   if (theOperation) {
-    ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
+    ModuleBase_OperationFeature* aFeatureOp =
+      dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
     if (aFeatureOp) {
-      CompositeFeaturePtr aFeature = 
+      CompositeFeaturePtr aFeature =
         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureOp->feature());
       if (aFeature && (aFeature->getKind() == SketchPlugin_Sketch::ID()))
         return PartSet_Tools::sketchPlane(aFeature);
     }
   }
-  return aEmptyPln; 
+  return aEmptyPln;
 }
 
 
 bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
 {
-  ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
+  ModuleBase_OperationFeature* aFeatureOp =
+    dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
   // during the create operation empty selection is always valid
   if (!aFeatureOp->isEditOperation()) {
     return true;
@@ -102,71 +131,97 @@ bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
       std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
       if (aPlane.get())
         return true;
-      else 
+      else
         return false;
     }
-    else// in edit operation an empty selection is always valid, performed for re-entrant operrations
+    else
+      // in edit operation an empty selection is always valid, performed for re-entrant operrations
       return true;
   }
 }
 
-bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_DistanceSelection::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) + shapesNbLines(theSelection);
-    return (aCount > 0) && (aCount < 3);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return (aNbPoints >= 0 && aNbPoints < 3) &&
+           (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges >= 0 && aNbEdges < 2);
   }
 }
 
-bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_LengthSelection::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);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges == 1);
+  }
+}
+
+bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                             ModuleBase_Operation* theOperation) const
+{
+  if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
+    return isEmptySelectionValid(theOperation);
+  } else {
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
   }
 }
 
-bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+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);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
   }
 }
 
-bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_RadiusSelection::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);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && (aShapes[GeomAbs_Circle] == aNbEdges && aNbEdges == 1);
   }
 }
 
-bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+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<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
-    ModuleBase_ViewerPrs aPrs;
+    QList<ModuleBase_ViewerPrsPtr> aList =
+      theSelection->getSelected(ModuleBase_ISelection::Viewer);
     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)
+    foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
+      ObjectPtr aObj = aPrs->object();
+      if (aObj.get()) {
+        FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
+        if (aFeature.get()) {
+          CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
+          if (aComp.get() && (aComp->getKind() == SketchPlugin_Sketch::ID()))
             aCount++;
         }
       }
@@ -175,145 +230,153 @@ bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection,
   }
 }
 
-bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+
+bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                          ModuleBase_Operation* theOperation) const
 {
   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
     return isEmptySelectionValid(theOperation);
   } else {
-    QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
-    return (aList.count() == 1);
+    // Coincident can be applied to points and to lines
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return (aNbPoints >= 0 && aNbPoints < 3) && (aNbEdges >= 0 && aNbEdges < 2);
   }
 }
 
+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 aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges == 1);
+  }
+}
 
-bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_FilletSelection::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);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aCount > 1 && aNbEdges == 0;
   }
 }
 
-bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_TangentSelection::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);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && (aNbEdges == 1 || (aNbEdges == 2 && aShapes[GeomAbs_Line] == 1));
   }
 }
 
-bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+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);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
   }
 }
 
-bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+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<ModuleBase_ViewerPrs> 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<GeomAPI_Shape> 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<GeomAPI_Shape> 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;
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && (aNbEdges > 0 && aNbEdges < 3) &&
+           (aShapes[GeomAbs_Line] == aNbEdges ||
+            aShapes[GeomAbs_Circle] == aNbEdges ||
+            aShapes[GeomAbs_Ellipse] == aNbEdges);
   }
 }
 
-bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_CollinearSelection::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);
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
+  }
+}
+
+bool PartSet_MiddlePointSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                           ModuleBase_Operation* theOperation) const
+{
+  if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0)
+    return isEmptySelectionValid(theOperation);
+  else {
+    int aNbPoints = shapesNbPoints(theSelection);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return (aNbPoints >= 0 && aNbPoints < 3) && (aNbEdges >= 0 && aNbEdges < 2);
   }
 }
 
-bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
+bool PartSet_MultyTranslationSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                     ModuleBase_Operation* theOperation) const
 {
   if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
     return isEmptySelectionValid(theOperation);
   } else {
-    QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
-    ModuleBase_ViewerPrs aPrs;
-    int aCount = 0;
-    int aType = 0;
-    foreach (ModuleBase_ViewerPrs aPrs, aList) {
-      std::shared_ptr<GeomAPI_Shape> 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);
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbEdges > 0;
   }
 }
 
+bool PartSet_SplitSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                     ModuleBase_Operation* theOperation) const
+{
+  if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
+    return isEmptySelectionValid(theOperation);
+  } else {
+    ShapeQuantity aShapes;
+    int aNbEdges = shapesNbEdges(theSelection, aShapes);
+    return aNbEdges > 0;
+  }
+}
+
+bool PartSet_ProjectionSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                     ModuleBase_Operation* theOperation) const
+{
+  return theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0 &&
+         isEmptySelectionValid(theOperation);
+}
+
+bool PartSet_IntersectionSelection::isValid(const ModuleBase_ISelection* theSelection,
+                                     ModuleBase_Operation* theOperation) const
+{
+  return theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0 &&
+         isEmptySelectionValid(theOperation);
+}
+
 
 std::string PartSet_DifferentObjectsValidator::errorMessage(
                          const PartSet_DifferentObjectsValidator::ErrorType& theType,
@@ -345,40 +408,43 @@ std::string PartSet_DifferentObjectsValidator::errorMessage(
   return anError;
 }
 
-bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, 
+bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
                                                 const std::list<std::string>& theArguments,
-                                                std::string& theError) const
+                                                Events_InfoMessage& theError) const
 {
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
 
-  // the type of validated attributes should be equal, attributes with different types are not validated
+  // 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<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
 
   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
-    AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+    AttributeRefAttrPtr anAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(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<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
-      for(; anAttr != anAttrs.end(); anAttr++) {
-      if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
+      std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
+      for(; anAttrIter != anAttrs.end(); anAttrIter++) {
+      if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
-                                      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
+                              std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
           if (aRef->isObject() != isObject)
             continue;
           if (isObject) {
             if (aRef->object() == anObject) {
-              theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
-                                      theAttribute->id(), aRef->id());
+              theError = errorMessage(EqualObjects,
+                anObject.get() ? Locale::Convert::toString(anObject->data()->name()) : "",
+                theAttribute->id(), aRef->id());
               return false;
             }
           }
           else { // the attribute reference
+            AttributePtr anAttributeAttr = anAttr->attr();
             if (aRef->attr() == anAttributeAttr) {
               theError = errorMessage(EqualAttributes,
                                       anAttributeAttr.get() ? anAttributeAttr->id() : "",
@@ -391,9 +457,11 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
     }
   }
   else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
-    AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
-    ResultPtr aContext = anAttr->context();
-    GeomShapePtr aShape = anAttr->value();
+    AttributeSelectionPtr anAttrSel =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+    ResultPtr aContext = anAttrSel->context();
+    FeaturePtr aContextFeature = anAttrSel->contextFeature();
+    GeomShapePtr aShape = anAttrSel->value();
 
     // Check selection attributes
     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
@@ -402,7 +470,7 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
       for(; anAttr != anAttrs.end(); anAttr++) {
         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
           std::shared_ptr<ModelAPI_AttributeSelection> aRef =
-                                        std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
+                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
           // check the object is already presented
           if (aRef->context() == aContext) {
             bool aHasShape = aShape.get() != NULL;
@@ -411,13 +479,32 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
               return false;
             }
           }
+          // check the whole selected feature contains the result
+          if (aContextFeature.get()) {
+            if (aRef->contextFeature().get()) {
+              if (aContextFeature == aRef->contextFeature()) {
+                theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
+                return false;
+              }
+            } else if (aRef->context().get() &&
+                aRef->context()->document()->feature(aRef->context()) == aContextFeature) {
+              theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
+              return false;
+            }
+          } else if (aRef->contextFeature().get() && aContext.get()) {
+            if (aContext->document()->feature(aContext) == aRef->contextFeature()) {
+              theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
+              return false;
+            }
+          }
         }
       }
     }
   }
   else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
-    AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
-    ObjectPtr anObject = anAttr->value();
+    AttributeReferencePtr anAttrRef =
+      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
+    ObjectPtr anObject = anAttrRef->value();
     // Check selection attributes
     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
     if (anAttrs.size() > 0) {
@@ -428,29 +515,31 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
             std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
           // check the object is already presented
           if (aRef->value() == anObject) {
-            theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
-                                    theAttribute->id(), aRef->id());
+            theError = errorMessage(EqualObjects,
+              anObject.get() ? Locale::Convert::toString(anObject->data()->name()) : "",
+              theAttribute->id(), aRef->id());
             return false;
           }
         }
-        return true;
       }
+      return true;
     }
   }
   else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
-    std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList = 
+    std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
     if(anAttrs.size() > 0) {
       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
       for(; anAttrItr != anAttrs.end(); anAttrItr++){
         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
-          std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList = 
+          std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
           for(int i = 0; i < aCurSelList->size(); i++) {
             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
             ResultPtr aCurSelContext = aCurSel->context();
-            ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
+            FeaturePtr aCurSelFeature = aCurSel->contextFeature();
+            ResultBodyPtr aCurSelCompSolidPtr = ModelAPI_Tools::bodyOwner(aCurSelContext);
             std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
             if(aCurSelCompSolidPtr.get()) {
               aCurSelCompSolid = aCurSelCompSolidPtr->shape();
@@ -458,26 +547,47 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
             for(int j = 0; j < aRefSelList->size(); j++) {
               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
               ResultPtr aRefSelContext = aRefSel->context();
-              ResultCompSolidPtr aRefSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aRefSelContext);
+              FeaturePtr aRefSelFeature = aRefSel->contextFeature();
+              ResultBodyPtr aRefSelCompSolidPtr =
+                ModelAPI_Tools::bodyOwner(aRefSelContext);
               std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
-              if(aRefSelCompSolidPtr.get()) {
+              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;
+                theError = errorMessage(EqualShapes, "", theAttribute->id(),
+                  aRefSel->id());
+                return false;
               }
-              if(aCurSelContext == aRefSelContext) {
+              if (aCurSelContext == aRefSelContext) {
                 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
-                  theError = errorMessage(EmptyShapes, "", theAttribute->id(),
-                                          aRefSel->id());
+                  theError = errorMessage(EmptyShapes, "", theAttribute->id(), aRefSel->id());
                   return false;
                 }
                 if (aCurSel->value()->isEqual(aRefSel->value())) {
-                  theError = errorMessage(EqualShapes, "", theAttribute->id(),
-                                          aRefSel->id());
+                  theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
+                  return false;
+                }
+              }
+
+              // check the whole selected feature contains the result
+              if (aCurSelFeature.get()) {
+                if (aRefSelFeature.get()) {
+                  if (aCurSelFeature == aRefSelFeature) {
+                    theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
+                    return false;
+                  }
+                }
+                else if (aRefSelContext.get() &&
+                  aRefSelContext->document()->feature(aRefSelContext) == aCurSelFeature) {
+                  theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
+                  return false;
+                }
+              }
+              else if (aRefSelFeature.get() && aCurSelContext.get()) {
+                if (aCurSelContext->document()->feature(aCurSelContext) == aRefSelFeature) {
+                  theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
                   return false;
                 }
               }
@@ -502,8 +612,9 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
             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());
+                  aCurSelObject.get()?
+                  Locale::Convert::toString(aCurSelObject->data()->name()) : "",
+                  theAttribute->id(), aCurSelList->id());
                 return false;
               }
             }
@@ -515,96 +626,73 @@ bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute
   return true;
 }
 
-bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
-                                            const std::list<std::string>& theArguments,
-                                            std::string& theError) const
+bool PartSet_DifferentPointsValidator::isValid(const AttributePtr& theAttribute,
+                                               const std::list<std::string>& theArguments,
+                                               Events_InfoMessage& theError) const
 {
-  bool isSketchEntities = true;
-  std::set<std::string> anEntityKinds;
-  std::string anEntityKindsStr;
-  std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
-  for (; anIt != aLast; anIt++) {
-    anEntityKinds.insert(*anIt);
-    if (!anEntityKindsStr.empty())
-      anEntityKindsStr += ", ";
-    anEntityKindsStr += *anIt;
-  }
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
 
-  std::string anAttributeType = theAttribute->attributeType();
-  if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
-    AttributeSelectionListPtr aSelectionListAttr = 
-                      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
-    // all context objects should be sketch entities
-    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_AttributeRefList::typeId()) {
-    AttributeRefListPtr aRefListAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(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<ModelAPI_AttributeRefAttr> aRef = 
-                     std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-    isSketchEntities = false;
-    if (aRef->isObject()) {
-      ObjectPtr anObject = aRef->object();
-      if (anObject.get() != NULL) {
-        FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
-        if (aFeature.get() != NULL)
-          isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
-      }
+  // 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<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
+  if (anAttrType != ModelAPI_AttributeRefAttr::typeId())
+    return true;
+
+  // obtain point of the given attribute
+  AttributePoint2DPtr anAttributePoint = getRefPointAttribute(theAttribute);
+  if (!anAttributePoint.get() || !anAttributePoint->isInitialized())
+    return true;
+
+  // obtain point of the parameter attribute
+  AttributePoint2DPtr anArgumentPoint = getRefPointAttribute
+                                              (aFeature->attribute(theArguments.front()));
+
+  if (!anArgumentPoint.get() || !anArgumentPoint->isInitialized())
+    return true;
+
+  return !anAttributePoint->pnt()->isEqual(anArgumentPoint->pnt());
+}
+
+AttributePoint2DPtr PartSet_DifferentPointsValidator::getRefPointAttribute
+                                                     (const AttributePtr& theAttribute) const
+{
+  AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+
+  AttributePoint2DPtr aPointAttribute;
+  if (anAttr->isObject()) {
+    ObjectPtr anObject  = anAttr->object();
+    if (anObject.get()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+      if (aFeature->getKind() == SketchPlugin_Point::ID())
+        aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+                                          (aFeature->attribute(SketchPlugin_Point::COORD_ID()));
     }
   }
-  if (!isSketchEntities) {
-    theError = "It refers to feature, which kind is not in the list: " + anEntityKindsStr;
+  else {
+    aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
   }
-
-  return isSketchEntities;
+  return aPointAttribute;
 }
 
-bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute, 
+bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
                                      const std::list<std::string>& 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;
   }
 
   // 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<ModelAPI_Feature>(theAttribute->owner());
   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
   QList<FeaturePtr> aCoinsideLines;
+  QList<FeaturePtr> aCoins;
 
   bool isObject = aRefAttr->isObject();
   ObjectPtr anObject = aRefAttr->object();
@@ -630,10 +718,13 @@ bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
         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());
+        QList<bool> anIsAttributes;
+        PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
+                                        SketchPlugin_ConstraintCoincidence::ENTITY_A(),
+                                        anIsAttributes);
+        PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
+                                        SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+                                        anIsAttributes);
       }
     }
     // if there is no coincidence then it is not valid
@@ -650,4 +741,3 @@ bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
   theError = "There is no a common coincident point.";
   return false;
 }
-