From: azv Date: Mon, 10 Apr 2017 13:03:28 +0000 (+0300) Subject: Issue #2117: Problem when creating an arc by 3 points ending on the same circle X-Git-Tag: V_2.7.0~24 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=3573047041a5379fa65949aac9277381afbf8b14;p=modules%2Fshaper.git Issue #2117: Problem when creating an arc by 3 points ending on the same circle --- diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index 3b12526d6..65a5cf662 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -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", diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 8e3dfabb4..98a6c1524 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -151,6 +151,79 @@ std::set 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 >::iterator aFound1 = find(thePoint1); + std::list< std::set >::iterator aFound2 = find(thePoint2); + if (aFound1 == myCoincidentPoints.end()) { + std::set 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 coincidentPoints(const AttributePoint2DPtr& thePoint) + { + std::list< std::set >::iterator aFound = find(thePoint); + if (aFound == myCoincidentPoints.end()) + return std::set(); + return *aFound; + } + +private: + std::list< std::set >::iterator find(const AttributePoint2DPtr& thePoint) + { + std::list< std::set >::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 > myCoincidentPoints; +}; + +std::set findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint) +{ + CoincidentPoints aCoincidentPoints; + AttributePoint2DPtr aPoints[2]; + + FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner()); + std::set aCoincidences = findCoincidentConstraints(anOwner); + std::set::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(aRefAttr->attr()); + } + + if (aPoints[0]) + aCoincidentPoints.addCoincidence(aPoints[0], aPoints[1]); + } + + return aCoincidentPoints.coincidentPoints(thePoint); +} + void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId) { diff --git a/src/SketchPlugin/SketchPlugin_Tools.h b/src/SketchPlugin/SketchPlugin_Tools.h index cecc946fc..ac2a6cd36 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.h +++ b/src/SketchPlugin/SketchPlugin_Tools.h @@ -39,6 +39,9 @@ void findCoincidences(const FeaturePtr theStartCoin, /// Find all features the point is coincident to. std::set findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint); +/// Find all points the given point is coincident to. +std::set findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint); + void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId); /// Creates coincidence or tangent constraint. diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 37caf1214..c0d9837e4 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -1069,6 +1069,39 @@ bool SketchPlugin_DifferentReferenceValidator::isValid( return isOk; } +bool SketchPlugin_DifferentPointReferenceValidator::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); + std::set aReferredCoincidentPoints; + + // find all points referred by attributes listed in theArguments + bool hasRefsToPoints = false; + std::list::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(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&, diff --git a/src/SketchPlugin/SketchPlugin_Validators.h b/src/SketchPlugin/SketchPlugin_Validators.h index bea581a48..bc74e092b 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@ -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& theArguments, + Events_InfoMessage& theError) const; +}; + /**\class SketchPlugin_CirclePassedPointValidator * \ingroup Validators * \brief Validator for passed point of MacroCircle feature. diff --git a/src/SketchPlugin/Test/TestCreateArcByThreePoints.py b/src/SketchPlugin/Test/TestCreateArcByThreePoints.py index 06f3d9903..d136ceab4 100644 --- a/src/SketchPlugin/Test/TestCreateArcByThreePoints.py +++ b/src/SketchPlugin/Test/TestCreateArcByThreePoints.py @@ -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() diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 57d57f82e..444209e88 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -237,7 +237,8 @@ tooltip="End point" accept_expressions="0" enable_value="enable_by_preferences"> - + +