From 090aa7bcfd1d7c8f74a28a8268a1e1b8008af4ca Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 27 Feb 2018 12:58:01 +0300 Subject: [PATCH] Issue #2157: Fix incorrect searching of features coincident to fillet point (special case when features coincident to external features) --- src/SketchPlugin/CMakeLists.txt | 1 + src/SketchPlugin/SketchPlugin_Fillet.cpp | 6 +- src/SketchPlugin/SketchPlugin_Tools.cpp | 71 +++++++++++++++++------- src/SketchPlugin/Test/Test2157_2.py | 46 +++++++++++++++ 4 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 src/SketchPlugin/Test/Test2157_2.py diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 34ddf4b9a..789bb9508 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -236,6 +236,7 @@ ADD_UNIT_TESTS(TestSketchPointLine.py Test2425.py Test2440.py Test2157.py + Test2157_2.py ) if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE}) diff --git a/src/SketchPlugin/SketchPlugin_Fillet.cpp b/src/SketchPlugin/SketchPlugin_Fillet.cpp index d2e46b7c3..519bb30c6 100644 --- a/src/SketchPlugin/SketchPlugin_Fillet.cpp +++ b/src/SketchPlugin/SketchPlugin_Fillet.cpp @@ -208,8 +208,10 @@ bool SketchPlugin_Fillet::calculateFilletParameters() std::set aFilletFeatures; for (std::set::iterator aCPIt = aCoincidentPoints.begin(); aCPIt != aCoincidentPoints.end(); ++aCPIt) { - FeaturePtr anOwner = ModelAPI_Feature::feature((*aCPIt)->owner()); - if (anOwner) + std::shared_ptr anOwner = + std::dynamic_pointer_cast( + ModelAPI_Feature::feature((*aCPIt)->owner())); + if (anOwner && !anOwner->isExternal()) aFilletFeatures.insert(anOwner); } if (aFilletFeatures.size() != 2) { diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 758de8b29..fb6401e11 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -207,6 +207,8 @@ public: std::set coincidentPoints(const AttributePoint2DPtr& thePoint) { + collectCoincidentPoints(thePoint); + std::list< std::set >::iterator aFound = find(thePoint); if (aFound == myCoincidentPoints.end()) return std::set(); @@ -214,6 +216,55 @@ public: } private: + void coincidences(const FeaturePtr& theFeature, + std::set& theCoincidences) const + { + // iterate through coincideces for the given feature + std::set aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature); + std::set::const_iterator aCIt = aCoincidences.begin(); + for (; aCIt != aCoincidences.end(); ++aCIt) + { + if (theCoincidences.find(*aCIt) != theCoincidences.end()) + continue; // already processed + theCoincidences.insert(*aCIt); + // iterate on coincident attributes + for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { + AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + if (aRefAttr && !aRefAttr->isObject()) + { + FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner()); + if (anOwner != theFeature) + coincidences(anOwner, theCoincidences); + } + } + } + } + + // Iteratively search points coincident to the given point + // (two points may be coincident through the third point) + void collectCoincidentPoints(const AttributePoint2DPtr& thePoint) + { + AttributePoint2DPtr aPoints[2]; + + FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner()); + std::set aCoincidences; + coincidences(anOwner, aCoincidences); + + 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 && !aRefAttr->isObject()) + aPoints[aPtInd++] = std::dynamic_pointer_cast(aRefAttr->attr()); + } + + if (aPoints[0] && aPoints[1]) + addCoincidence(aPoints[0], aPoints[1]); + } + } + std::list< std::set >::iterator find(const AttributePoint2DPtr& thePoint) { std::list< std::set >::iterator aSeek = myCoincidentPoints.begin(); @@ -230,26 +281,6 @@ private: 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); } diff --git a/src/SketchPlugin/Test/Test2157_2.py b/src/SketchPlugin/Test/Test2157_2.py new file mode 100644 index 000000000..c15f1d6ee --- /dev/null +++ b/src/SketchPlugin/Test/Test2157_2.py @@ -0,0 +1,46 @@ +## Copyright (C) 2018-20xx CEA/DEN, EDF R&D +## +## 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 +## + +from SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_1 = SketchProjection_1.createdFeature() +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False) +SketchLine_2 = SketchProjection_2.createdFeature() +SketchLine_3 = Sketch_1.addLine(60, 10, 0, 0) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_3.endPoint()) +SketchLine_4 = Sketch_1.addLine(20, 50, 0, 0) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchLine_4.endPoint()) +model.do() + +SketchFillet_1 = Sketch_1.setFillet(SketchLine_3.endPoint()) +model.do() + +assert(Sketch_1.feature().error() == "") +assert(Sketch_1.solverError().value() == "") + +model.end() -- 2.39.2