]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #2117: Problem when creating an arc by 3 points ending on the same circle
authorazv <azv@opencascade.com>
Mon, 10 Apr 2017 13:03:28 +0000 (16:03 +0300)
committerazv <azv@opencascade.com>
Mon, 10 Apr 2017 13:03:28 +0000 (16:03 +0300)
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/Test/TestCreateArcByThreePoints.py
src/SketchPlugin/plugin-Sketch.xml

index 3b12526d65f173073c1bca9a414f0feb96dc4a64..65a5cf66212571e323f4fa077a05e0600495e8c8 100644 (file)
@@ -98,6 +98,8 @@ SketchPlugin_Plugin::SketchPlugin_Plugin()
                               new SketchPlugin_ProjectionValidator);
   aFactory->registerValidator("SketchPlugin_DifferentReference",
                               new SketchPlugin_DifferentReferenceValidator);
+  aFactory->registerValidator("SketchPlugin_DifferentPointReference",
+                              new SketchPlugin_DifferentPointReferenceValidator);
   aFactory->registerValidator("SketchPlugin_CirclePassedPointValidator",
                               new SketchPlugin_CirclePassedPointValidator);
   aFactory->registerValidator("SketchPlugin_ThirdPointValidator",
index 8e3dfabb404b9f881a8a97faec530495a21414b4..98a6c1524892e146daf313f59eb3fdaff6a57799 100644 (file)
@@ -151,6 +151,79 @@ std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& th
   return aCoincidentFeatures;
 }
 
+// Container for point-point coincidences.
+// Useful to find points coincident to a given point.
+class CoincidentPoints
+{
+public:
+  void addCoincidence(const AttributePoint2DPtr& thePoint1,
+                      const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
+  {
+    std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
+    std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
+    if (aFound1 == myCoincidentPoints.end()) {
+      std::set<AttributePoint2DPtr> aNewSet;
+      aNewSet.insert(thePoint1);
+      if (thePoint2)
+        aNewSet.insert(thePoint2);
+      myCoincidentPoints.push_back(aNewSet);
+    } else if (aFound2 == myCoincidentPoints.end()) {
+      if (thePoint2)
+        aFound1->insert(thePoint2);
+    } else {
+      aFound1->insert(aFound2->begin(), aFound2->end());
+      myCoincidentPoints.erase(aFound2);
+    }
+  }
+
+  std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
+  {
+    std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
+    if (aFound == myCoincidentPoints.end())
+      return std::set<AttributePoint2DPtr>();
+    return *aFound;
+  }
+
+private:
+  std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
+  {
+    std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
+    for (; aSeek != myCoincidentPoints.end(); ++aSeek)
+      if (aSeek->find(thePoint) != aSeek->end())
+        return aSeek;
+    return myCoincidentPoints.end();
+  }
+
+private:
+  std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
+};
+
+std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
+{
+  CoincidentPoints aCoincidentPoints;
+  AttributePoint2DPtr aPoints[2];
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
+  std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
+  std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+  for (; aCIt != aCoincidences.end(); ++aCIt) {
+    aPoints[0] = AttributePoint2DPtr();
+    aPoints[1] = AttributePoint2DPtr();
+    for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+      AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+      if (!aRefAttr)
+        continue;
+      if (!aRefAttr->isObject())
+        aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+    }
+
+    if (aPoints[0])
+      aCoincidentPoints.addCoincidence(aPoints[0], aPoints[1]);
+  }
+
+  return aCoincidentPoints.coincidentPoints(thePoint);
+}
+
 void resetAttribute(SketchPlugin_Feature* theFeature,
                     const std::string& theId)
 {
index cecc946fc6b4b00574fd1a5d52d68133af6e74d0..ac2a6cd36d86cf61cfbca084308dba705a968d34 100644 (file)
@@ -39,6 +39,9 @@ void findCoincidences(const FeaturePtr theStartCoin,
 /// Find all features the point is coincident to.
 std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint);
 
+/// Find all points the given point is coincident to.
+std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint);
+
 void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId);
 
 /// Creates coincidence or tangent constraint.
index 37caf12143bccc5901d129f3452eb7ec97140ff6..c0d9837e4c9aea20c95525c42cb7a58947146fab 100755 (executable)
@@ -1069,6 +1069,39 @@ bool SketchPlugin_DifferentReferenceValidator::isValid(
   return isOk;
 }
 
+bool SketchPlugin_DifferentPointReferenceValidator::isValid(
+    const AttributePtr& theAttribute,
+    const std::list<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+  std::set<AttributePoint2DPtr> aReferredCoincidentPoints;
+
+  // find all points referred by attributes listed in theArguments
+  bool hasRefsToPoints = false;
+  std::list<std::string>::const_iterator anArgIt = theArguments.begin();
+  for (; anArgIt != theArguments.end(); ++anArgIt) {
+    AttributeRefAttrPtr aRefAttr = anOwner->refattr(*anArgIt);
+    if (!aRefAttr)
+      continue;
+
+    if (!aRefAttr->isObject()) {
+      AttributePoint2DPtr aPoint =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+      if (aReferredCoincidentPoints.empty())
+        aReferredCoincidentPoints = SketchPlugin_Tools::findPointsCoincidentToPoint(aPoint);
+      else if (aReferredCoincidentPoints.find(aPoint) == aReferredCoincidentPoints.end())
+        return true; // non-coincident point has been found
+      else
+        hasRefsToPoints = true;
+    }
+  }
+
+  if (hasRefsToPoints)
+    theError = "Attributes are referred to the same point";
+  return !hasRefsToPoints;
+}
+
 bool SketchPlugin_CirclePassedPointValidator::isValid(
     const AttributePtr& theAttribute,
     const std::list<std::string>&,
index bea581a48633f19fce2cdf3e00ce255ece07d8c2..bc74e092b6d3bdb6de37becb7e93b255f2751a96 100644 (file)
@@ -311,6 +311,24 @@ class SketchPlugin_DifferentReferenceValidator : public ModelAPI_AttributeValida
                        Events_InfoMessage& theError) const;
 };
 
+/**\class SketchPlugin_DifferentPointReferenceValidator
+ * \ingroup Validators
+ * \brief Validator for attributes of a sketch feature.
+ *
+ * It checks that at least two of specified attributes refer to different points.
+ */
+class SketchPlugin_DifferentPointReferenceValidator : 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.
index 06f3d9903692f6fc541c4e99d65896be6f1d4631..d136ceab4bdf6ee83dad1c0581ab91d30c9584a8 100644 (file)
@@ -251,6 +251,46 @@ assert aLastFeature.getKind() == "SketchMacroArc", "ERROR: SketchMacroArc has NO
 aDocument.removeFeature(anArc)
 assert (aSketchFeature.numberOfSubs() == 9)
 
+#=========================================================================
+# Test 6. Create an arc by three points:
+#         a. check that one point IS NOT selectable as first and second points simultaneously
+#         b. check that one segment IS selectable by first and second points
+#=========================================================================
+aSession.startOperation()
+anArc = aSketchFeature.addFeature("SketchMacroArc")
+anArcPnt1 = geomDataAPI_Point2D(anArc.attribute("start_point_2"))
+anArcPnt2 = geomDataAPI_Point2D(anArc.attribute("end_point_2"))
+anArcPnt3 = geomDataAPI_Point2D(anArc.attribute("passed_point"))
+anArcPnt1Ref = anArc.refattr("start_point_ref")
+anArcPnt2Ref = anArc.refattr("end_point_ref")
+anArcPnt3Ref = anArc.refattr("passed_point_ref")
+anArcType = anArc.string("arc_type")
+# initialize attributes
+anArcType.setValue("by_three_points")
+anArcPnt1Ref.setAttr(aStartPnt)
+anArcPnt1.setValue(aStartPnt.pnt())
+anArcPnt2Ref.setAttr(aStartPnt)
+anArcPnt2.setValue(aStartPnt.pnt())
+anArcPnt3.setValue(0., 0.)
+aSession.finishOperation()
+# check the macro arc is not valid
+aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
+assert aLastFeature.getKind() == "SketchMacroArc", "ERROR: SketchMacroArc has NOT expected to be valid"
+# reselect first points
+aSession.startOperation()
+anArcPnt1Ref.setObject(aLine.lastResult())
+anArcPnt1.setValue(aStartPnt.pnt())
+anArcPnt2Ref.setObject(aLine.lastResult())
+anArcPnt2.setValue(aEndPnt.pnt())
+aSession.finishOperation()
+# check the macro arc is valid
+aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
+assert aLastFeature.getKind() != "SketchMacroArc", "ERROR: SketchMacroArc is expected to be valid"
+assert (aSketchFeature.numberOfSubs() == 12)
+# check sub-features
+model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 5)
+model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 1)
+
 model.do()
 model.end()
 
index 57d57f82e1b32f2dd299ed30c7e7fabd9f209c4a..444209e88a8228554f7fa6b8af8a9e7235d41082 100644 (file)
                                      tooltip="End point"
                                      accept_expressions="0"
                                      enable_value="enable_by_preferences">
-              <validator id="SketchPlugin_DifferentReference" parameters="start_point_ref,end_point_ref"/>
+              <validator id="GeomValidators_Different" parameters="start_point_2,end_point_2"/>
+              <validator id="SketchPlugin_DifferentPointReference" parameters="start_point_ref,end_point_ref"/>
             </sketch-2dpoint_selector>
             <sketch-2dpoint_selector id="passed_point"
                                      reference_attribute="passed_point_ref"