Salome HOME
Issue #2024: Redesign of circle and arc of circle
authorazv <azv@opencascade.com>
Fri, 24 Mar 2017 12:24:38 +0000 (15:24 +0300)
committerdbv <dbv@opencascade.com>
Mon, 27 Mar 2017 06:56:55 +0000 (09:56 +0300)
Implement validators for MacroCircle feature

src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_Tools.cpp
src/SketchPlugin/SketchPlugin_Tools.h
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/SketchPlugin_Validators.h
src/SketchPlugin/plugin-Sketch.xml

index 53d44428de64414af073947042c166f45d713265..c09102540a14aec4501020a33c1719fe1e17a91e 100644 (file)
@@ -90,6 +90,12 @@ SketchPlugin_Plugin::SketchPlugin_Plugin()
                               new SketchPlugin_IntersectionValidator);
   aFactory->registerValidator("SketchPlugin_ProjectionValidator",
                               new SketchPlugin_ProjectionValidator);
+  aFactory->registerValidator("SketchPlugin_DifferentReference",
+                              new SketchPlugin_DifferentReferenceValidator);
+  aFactory->registerValidator("SketchPlugin_CirclePassedPointValidator",
+                              new SketchPlugin_CirclePassedPointValidator);
+  aFactory->registerValidator("SketchPlugin_ThirdPointValidator",
+                              new SketchPlugin_ThirdPointValidator);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
index 9a4d82f848e9d425223463ff6634d38b178fdb02..5758a6b7d25fb7a2b3563e2ee61b817492db3903 100644 (file)
@@ -75,6 +75,19 @@ std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin
   return aPnt;
 }
 
+std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
+{
+  std::set<FeaturePtr> aCoincident;
+  const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
+  std::set<AttributePtr>::const_iterator aIt;
+  for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
+    FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
+    if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+      aCoincident.insert(aConstrFeature);
+  }
+  return aCoincident;
+}
+
 void findCoincidences(const FeaturePtr theStartCoin,
                       const std::string& theAttr,
                       std::set<FeaturePtr>& theList)
@@ -90,22 +103,54 @@ void findCoincidences(const FeaturePtr theStartCoin,
       return;
     }
     theList.insert(aObj);
-    const std::set<AttributePtr>& aRefsList = aObj->data()->refsToMe();
-    std::set<AttributePtr>::const_iterator aIt;
-    for(aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
-      std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
-      FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
-      if(aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
-        std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
-        if(aPnt.get() && aOrig->isEqual(aPnt)) {
-          findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList);
-          findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList);
-        }
+    std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
+    std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+    for (; aCIt != aCoincidences.end(); ++aCIt) {
+      FeaturePtr aConstrFeature = *aCIt;
+      std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
+      if(aPnt.get() && aOrig->isEqual(aPnt)) {
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList);
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList);
       }
     }
   }
 }
 
+std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
+{
+  std::set<FeaturePtr> aCoincidentFeatures;
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
+  aCoincidentFeatures.insert(anOwner);
+
+  std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
+  std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+  for (; aCIt != aCoincidences.end(); ++aCIt) {
+    bool isPointUsedInCoincidence = false;
+    AttributeRefAttrPtr anOtherCoincidentAttr;
+    for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+      AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+      if (!aRefAttr)
+        continue;
+      if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
+        isPointUsedInCoincidence = true;
+      else
+        anOtherCoincidentAttr = aRefAttr;
+    }
+
+    if (isPointUsedInCoincidence) {
+      ObjectPtr anObj;
+      if (anOtherCoincidentAttr->isObject())
+        anObj = anOtherCoincidentAttr->object();
+      else
+        anObj = anOtherCoincidentAttr->attr()->owner();
+      aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
+    }
+  }
+
+  return aCoincidentFeatures;
+}
+
 void resetAttribute(SketchPlugin_Feature* theFeature,
                     const std::string& theId)
 {
index 6d588b5d38df180f214ada1aa0801d7d8bb88920..622b63d68705d6b06e44e28602d5e4e51a0ee905 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Attribute.h>
+#include <GeomDataAPI_Point2D.h>
 
 class SketchPlugin_Feature;
 
@@ -23,6 +24,9 @@ void clearExpressions(FeaturePtr theFeature);
 /// \param[in] theStartCoin coincidence feature
 std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin);
 
+/// Find all Coincident constraints referred to the feature or its attribute
+std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature);
+
 /// Finds lines coincident at point
 /// \param[in] theStartCoin coincidence feature
 /// \param[in] theAttr attribute name
@@ -31,6 +35,9 @@ void findCoincidences(const FeaturePtr theStartCoin,
                       const std::string& theAttr,
                       std::set<FeaturePtr>& theList);
 
+/// Find all features the point is coincident to.
+std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint);
+
 void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId);
 
 /// Creates coincidence or tangent constraint.
index cb4b746b6de81389b3a75f4d5afef7170952ebf1..ce6ee3b3485f531fe145fbed96bfb7f78ffa5e98 100755 (executable)
 #include "SketchPlugin_Circle.h"
 #include "SketchPlugin_ConstraintCoincidence.h"
 #include "SketchPlugin_ConstraintDistance.h"
-#include "SketchPlugin_Fillet.h"
 #include "SketchPlugin_ConstraintRigid.h"
 #include "SketchPlugin_ConstraintTangent.h"
+#include "SketchPlugin_Fillet.h"
 #include "SketchPlugin_Line.h"
+#include "SketchPlugin_MacroCircle.h"
 #include "SketchPlugin_Point.h"
 #include "SketchPlugin_Sketch.h"
 #include "SketchPlugin_Trim.h"
@@ -40,6 +41,7 @@
 #include <ModelGeomAlgo_Shape.h>
 
 #include <GeomAPI_Circ.h>
+#include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Lin.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Vertex.h>
@@ -998,3 +1000,277 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
   theError = "Error: Selected object is not line, circle or arc.";
   return false;
 }
+
+
+static std::set<FeaturePtr> common(const std::set<FeaturePtr>& theSet1,
+                                   const std::set<FeaturePtr>& theSet2)
+{
+  std::set<FeaturePtr> aCommon;
+  if (theSet1.empty() || theSet2.empty())
+    return aCommon;
+
+  std::set<FeaturePtr>::const_iterator anIt2 = theSet2.begin();
+  for (; anIt2 != theSet2.end(); ++anIt2)
+    if (theSet1.find(*anIt2) != theSet1.end())
+      aCommon.insert(*anIt2);
+  return aCommon;
+}
+
+bool SketchPlugin_DifferentReferenceValidator::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+
+  int aNbFeaturesReferred = 0;
+  int aNbAttributesReferred = 0;
+  std::set<FeaturePtr> aCommonReferredFeatures;
+
+  // find all features referred by attributes listed in theArguments
+  std::list<std::string>::const_iterator anArgIt = theArguments.begin();
+  for (; anArgIt != theArguments.end(); ++anArgIt) {
+    AttributeRefAttrPtr aRefAttr = anOwner->refattr(*anArgIt);
+    if (!aRefAttr)
+      continue;
+
+    std::set<FeaturePtr> aCoincidentFeatures;
+    if (aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      if (aFeature) {
+        aCoincidentFeatures.insert(aFeature);
+        aNbFeaturesReferred += 1;
+      }
+    } else {
+      AttributePoint2DPtr aPoint =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+      if (aPoint) {
+        aCoincidentFeatures = SketchPlugin_Tools::findFeaturesCoincidentToPoint(aPoint);
+        aNbAttributesReferred += 1;
+      }
+    }
+
+    if (aCommonReferredFeatures.empty())
+      aCommonReferredFeatures = aCoincidentFeatures;
+    else
+      aCommonReferredFeatures = common(aCommonReferredFeatures, aCoincidentFeatures);
+
+    if (aCommonReferredFeatures.empty())
+      return true;
+  }
+
+  bool isOk = aNbFeaturesReferred < 1;
+  if (aNbFeaturesReferred == 1) {
+    if (aCommonReferredFeatures.size() == 1) {
+      FeaturePtr aFeature = *aCommonReferredFeatures.begin();
+      isOk = aNbAttributesReferred <= 1 ||
+             aFeature->getKind() == SketchPlugin_Circle::ID() ||
+             aFeature->getKind() == SketchPlugin_Arc::ID();
+    } else
+      isOk = false;
+  }
+
+  if (!isOk)
+    theError = "Attributes are referred to the same feature";
+  return isOk;
+}
+
+bool SketchPlugin_CirclePassedPointValidator::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>&,
+    Events_InfoMessage& theError) const
+{
+  static const std::string aErrorMessage(
+      "Passed point refers to the same feature as a center point");
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+
+  AttributeRefAttrPtr aCenterRef =
+      anOwner->refattr(SketchPlugin_MacroCircle::CENTER_POINT_REF_ID());
+  AttributeRefAttrPtr aPassedRef =
+      anOwner->refattr(SketchPlugin_MacroCircle::PASSED_POINT_REF_ID());
+
+  if (!aPassedRef->isObject())
+    return true;
+
+  FeaturePtr aPassedFeature = ModelAPI_Feature::feature(aPassedRef->object());
+  if (!aPassedFeature)
+    return true;
+
+  if (aCenterRef->isObject()) {
+    FeaturePtr aCenterFeature = ModelAPI_Feature::feature(aCenterRef->object());
+    if (aCenterFeature == aPassedFeature) {
+      theError = aErrorMessage;
+      return false;
+    }
+  } else {
+    AttributePoint2DPtr aCenterPoint =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCenterRef->attr());
+    if (aCenterPoint) {
+      std::set<FeaturePtr> aCoincidentFeatures =
+          SketchPlugin_Tools::findFeaturesCoincidentToPoint(aCenterPoint);
+      // check one of coincident features is a feature referred by passed point
+      std::set<FeaturePtr>::const_iterator anIt = aCoincidentFeatures.begin();
+      for(; anIt != aCoincidentFeatures.end(); ++anIt)
+        if (*anIt == aPassedFeature) {
+          theError = aErrorMessage;
+          return false;
+        }
+    }
+  }
+  return true;
+}
+
+bool SketchPlugin_ThirdPointValidator::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>&,
+    Events_InfoMessage& theError) const
+{
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+  return arePointsNotOnLine(anOwner, theError) && arePointsNotSeparated(anOwner, theError);
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> toPoint(const FeaturePtr& theMacroCircle,
+                                              const std::string& thePointAttrName,
+                                              const std::string& theRefPointAttrName)
+{
+  AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theMacroCircle->attribute(thePointAttrName));
+  AttributeRefAttrPtr aRefAttr = theMacroCircle->refattr(theRefPointAttrName);
+
+  std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointAttr->pnt();
+  if (aRefAttr) {
+    if (aRefAttr->isObject()) {
+      // project a point onto selected feature
+      std::shared_ptr<SketchPlugin_Feature> aFeature =
+          std::dynamic_pointer_cast<SketchPlugin_Feature>(
+          ModelAPI_Feature::feature(aRefAttr->object()));
+      if (aFeature) {
+        SketchPlugin_Sketch* aSketch = aFeature->sketch();
+        std::shared_ptr<GeomAPI_Edge> anEdge =
+            std::dynamic_pointer_cast<GeomAPI_Edge>(aFeature->lastResult()->shape());
+        if (anEdge) {
+          std::shared_ptr<GeomAPI_Pnt> aPoint3D = aSketch->to3D(aPoint->x(), aPoint->y());
+          if (anEdge->isLine())
+            aPoint3D = anEdge->line()->project(aPoint3D);
+          else if (anEdge->isCircle())
+            aPoint3D = anEdge->circle()->project(aPoint3D);
+          aPoint = aSketch->to2D(aPoint3D);
+        }
+      }
+    } else {
+      AttributePoint2DPtr anOtherPoint =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+      if (anOtherPoint)
+        aPoint = anOtherPoint->pnt(); // the reference point is much more precise, use it
+    }
+  }
+
+  return aPoint;
+}
+
+static bool isPointsOnLine(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+                           const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+                           const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
+{
+  static const double aTolerance = 1.e-7;
+  if (thePoint1->distance(thePoint2) < aTolerance ||
+      thePoint1->distance(thePoint3) < aTolerance)
+    return true;
+
+  std::shared_ptr<GeomAPI_Dir2d> aDirP1P2(new GeomAPI_Dir2d(thePoint2->x() - thePoint1->x(),
+                                                            thePoint2->y() - thePoint1->y()));
+  std::shared_ptr<GeomAPI_Dir2d> aDirP1P3(new GeomAPI_Dir2d(thePoint3->x() - thePoint1->x(),
+                                                            thePoint3->y() - thePoint1->y()));
+  return fabs(aDirP1P2->cross(aDirP1P3)) < aTolerance;
+}
+
+static bool isOnSameSide(const std::shared_ptr<GeomAPI_Lin>& theLine,
+                         const std::shared_ptr<GeomAPI_Pnt>& thePoint1,
+                         const std::shared_ptr<GeomAPI_Pnt>& thePoint2)
+{
+  static const double aTolerance = 1.e-7;
+  std::shared_ptr<GeomAPI_Dir> aLineDir = theLine->direction();
+  std::shared_ptr<GeomAPI_XYZ> aLineLoc = theLine->location()->xyz();
+  std::shared_ptr<GeomAPI_Dir> aDirP1L(new GeomAPI_Dir(thePoint1->xyz()->decreased(aLineLoc)));
+  std::shared_ptr<GeomAPI_Dir> aDirP2L(new GeomAPI_Dir(thePoint2->xyz()->decreased(aLineLoc)));
+  return aLineDir->cross(aDirP1L)->dot(aLineDir->cross(aDirP2L)) > -aTolerance;
+}
+
+static bool isOnSameSide(const std::shared_ptr<GeomAPI_Circ>& theCircle,
+                         const std::shared_ptr<GeomAPI_Pnt>&  thePoint1,
+                         const std::shared_ptr<GeomAPI_Pnt>&  thePoint2)
+{
+  static const double aTolerance = 1.e-7;
+  std::shared_ptr<GeomAPI_Pnt> aCenter = theCircle->center();
+  double aDistP1C = thePoint1->distance(aCenter);
+  double aDistP2C = thePoint2->distance(aCenter);
+  return (aDistP1C - theCircle->radius()) * (aDistP2C - theCircle->radius()) > -aTolerance;
+}
+
+bool SketchPlugin_ThirdPointValidator::arePointsNotOnLine(
+    const FeaturePtr& theMacroCircle,
+    Events_InfoMessage& theError) const
+{
+  static const std::string aErrorPointsOnLine(
+      "Selected points are on the same line");
+
+  std::shared_ptr<GeomAPI_Pnt2d> aFirstPoint = toPoint(theMacroCircle,
+        SketchPlugin_MacroCircle::FIRST_POINT_ID(),
+        SketchPlugin_MacroCircle::FIRST_POINT_REF_ID());
+  std::shared_ptr<GeomAPI_Pnt2d> aSecondPoint = toPoint(theMacroCircle,
+        SketchPlugin_MacroCircle::SECOND_POINT_ID(),
+        SketchPlugin_MacroCircle::SECOND_POINT_REF_ID());
+  std::shared_ptr<GeomAPI_Pnt2d> aThirdPoint = toPoint(theMacroCircle,
+        SketchPlugin_MacroCircle::THIRD_POINT_ID(),
+        SketchPlugin_MacroCircle::THIRD_POINT_REF_ID());
+
+  if (isPointsOnLine(aFirstPoint, aSecondPoint, aThirdPoint)) {
+    theError = aErrorPointsOnLine;
+    return false;
+  }
+  return true;
+}
+
+bool SketchPlugin_ThirdPointValidator::arePointsNotSeparated(
+    const FeaturePtr& theMacroCircle,
+    Events_InfoMessage& theError) const
+{
+  static const std::string aErrorPointsApart(
+      "Selected entity is lying between first two points");
+
+  AttributeRefAttrPtr aThirdPointRef =
+      theMacroCircle->refattr(SketchPlugin_MacroCircle::THIRD_POINT_REF_ID());
+  FeaturePtr aRefByThird;
+  if (aThirdPointRef->isObject())
+    aRefByThird = ModelAPI_Feature::feature(aThirdPointRef->object());
+  if (!aRefByThird)
+    return true;
+
+  std::shared_ptr<GeomAPI_Pnt2d> aFirstPoint = toPoint(theMacroCircle,
+        SketchPlugin_MacroCircle::FIRST_POINT_ID(),
+        SketchPlugin_MacroCircle::FIRST_POINT_REF_ID());
+  std::shared_ptr<GeomAPI_Pnt2d> aSecondPoint = toPoint(theMacroCircle,
+        SketchPlugin_MacroCircle::SECOND_POINT_ID(),
+        SketchPlugin_MacroCircle::SECOND_POINT_REF_ID());
+
+  std::shared_ptr<GeomAPI_Edge> aThirdShape =
+      std::dynamic_pointer_cast<GeomAPI_Edge>(aRefByThird->lastResult()->shape());
+  if (!aThirdShape)
+    return true;
+
+  SketchPlugin_Sketch* aSketch =
+      std::dynamic_pointer_cast<SketchPlugin_Feature>(theMacroCircle)->sketch();
+  std::shared_ptr<GeomAPI_Pnt> aFirstPnt3D = aSketch->to3D(aFirstPoint->x(), aFirstPoint->y());
+  std::shared_ptr<GeomAPI_Pnt> aSecondPnt3D = aSketch->to3D(aSecondPoint->x(), aSecondPoint->y());
+
+  bool isOk = true;
+  if (aThirdShape->isLine())
+    isOk = isOnSameSide(aThirdShape->line(), aFirstPnt3D, aSecondPnt3D);
+  else if (aThirdShape->isCircle() || aThirdShape->isArc())
+    isOk = isOnSameSide(aThirdShape->circle(), aFirstPnt3D, aSecondPnt3D);
+
+  if (!isOk)
+    theError = aErrorPointsApart;
+  return isOk;
+}
index aaae2d95783e2bade6ab4bc715b58b6ab4979e03..3dfd9398d231e6d490054359e59f4680ee1dd0c6 100644 (file)
@@ -292,4 +292,70 @@ class SketchPlugin_ProjectionValidator : public ModelAPI_AttributeValidator
                        Events_InfoMessage& theError) const;
 };
 
+/**\class SketchPlugin_DifferentReferenceValidator
+ * \ingroup Validators
+ * \brief Validator for attributes of a sketch feature.
+ *
+ * It checks that at least one of specified attributes
+ * refers to another feature in respect to each other.
+ */
+class SketchPlugin_DifferentReferenceValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  //! returns true if attribute is valid
+  //! \param theAttribute the checked attribute
+  //! \param theArguments arguments of the attribute
+  //! \param theError error message
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
+/**\class SketchPlugin_CirclePassedPointValidator
+ * \ingroup Validators
+ * \brief Validator for passed point of MacroCircle feature.
+ *
+ * Checks that passed point does not refer to the feature, the center is coincident to.
+ */
+class SketchPlugin_CirclePassedPointValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  //! returns true if attribute is valid
+  //! \param theAttribute the checked attribute
+  //! \param theArguments arguments of the attribute
+  //! \param theError error message
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>&,
+                       Events_InfoMessage& theError) const;
+};
+
+/**\class SketchPlugin_ThirdPointValidator
+ * \ingroup Validators
+ * \brief Validator for the third point of MacroCircle feature.
+ *
+ * Checks that third point does not lie on a line passed through the first two points.
+ * Checks that third point does not refer to feature lying between the first two points.
+ */
+class SketchPlugin_ThirdPointValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  //! returns true if attribute is valid
+  //! \param theAttribute the checked attribute
+  //! \param theArguments arguments of the attribute
+  //! \param theError error message
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>&,
+                       Events_InfoMessage& theError) const;
+
+private:
+  //! returns true if three points have not been placed on the same line
+  bool arePointsNotOnLine(const FeaturePtr& theMacroCircle,
+                          Events_InfoMessage& theError) const;
+
+  //! returns true if the first two points have not been separated
+  //! by a feature referred by thrid point
+  bool arePointsNotSeparated(const FeaturePtr& theMacroCircle,
+                             Events_InfoMessage& theError) const;
+};
+
 #endif
index cf97eaa2110ee81ef8939f8c5f2c86c3b15804a9..8a11e16c501772080c206a2c3fd4d23c7385f9d6 100644 (file)
                                      title="Passed point"
                                      tooltip="Passed point coordinates"
                                      accept_expressions="0"
-                                     enable_value="enable_by_preferences"/>
+                                     enable_value="enable_by_preferences">
+              <validator id="SketchPlugin_CirclePassedPointValidator"/>
+            </sketch-2dpoint_selector>
+            <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/>
           </box>
           <box id="circle_type_by_three_points"
                icon="icons/Sketch/circle_3pt_32x32.png"
                                      title="Second point"
                                      tooltip="Second point"
                                      accept_expressions="0"
-                                     enable_value="enable_by_preferences"/>
+                                     enable_value="enable_by_preferences">
+              <validator id="SketchPlugin_DifferentReference" parameters="first_point_ref,second_point_ref"/>
+            </sketch-2dpoint_selector>
             <sketch-2dpoint_selector id="third_point"
                                      reference_attribute="third_point_ref"
                                      title="Third point"
                                      tooltip="Third point"
                                      accept_expressions="0"
-                                     enable_value="enable_by_preferences"/>
+                                     enable_value="enable_by_preferences">
+              <validator id="SketchPlugin_DifferentReference" parameters="first_point_ref,second_point_ref,third_point_ref"/>
+              <validator id="SketchPlugin_ThirdPointValidator"/>
+            </sketch-2dpoint_selector>
+            <validator id="GeomValidators_Different" parameters="first_point_ref,second_point_ref,third_point_ref"/>
           </box>
         </toolbox>
         <labelvalue id="circle_radius"