From a3c4a2b2e6fdc549165b6c660124a75367141a7b Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 15 Jan 2019 08:34:26 +0300 Subject: [PATCH] Issue #2824: Constraints at wrong positions when editing the sketch Improve updating the position of the odd point, which is used to keep the sign of a point-line distance constraint. There is also changed the order of the features to be updated by the SketchSolver: sketch features updated before constraints. --- src/SketchPlugin/CMakeLists.txt | 1 + src/SketchPlugin/Test/Test2824.py | 65 ++++++++++++++++ .../SketchSolver_ConstraintDistance.cpp | 74 +++++++++++++------ src/SketchSolver/SketchSolver_Manager.cpp | 66 +++++++++++------ 4 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 src/SketchPlugin/Test/Test2824.py diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 86fc7c4ad..a608c992c 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -192,6 +192,7 @@ ADD_UNIT_TESTS( Test2711.py Test2741.py Test2810.py + Test2824.py TestArcBehavior.py TestConstraintAngle.py TestConstraintCoincidence.py diff --git a/src/SketchPlugin/Test/Test2824.py b/src/SketchPlugin/Test/Test2824.py new file mode 100644 index 000000000..585af5a39 --- /dev/null +++ b/src/SketchPlugin/Test/Test2824.py @@ -0,0 +1,65 @@ +## 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 +## + +""" + Test2824.py + Test case for issue #2824 "Constraints at wrong positions when editing the sketch (BARCOM)" +""" + +from salome.shaper import model +from GeomAPI import * +from GeomDataAPI import * + +import math + +TOLERANCE = 1.e-6 + +model.begin() +partSet = model.moduleDocument() +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOZ")) +SketchArc_1 = Sketch_1.addArc(7.554548355024374, 9.322927740745062, 20, 30.60489708262655, 31.5458454490763, 15, True) +SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "OZ"), False) +SketchLine_1 = SketchProjection_1.createdFeature() +SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.startPoint(), SketchLine_1.result(), 20, True) +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "OX"), False) +SketchLine_2 = SketchProjection_2.createdFeature() +SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.endPoint(), SketchLine_2.result(), 15, True) +model.do() +# move the arc like the user does +for i in range(0, 10): + Sketch_1.move(SketchArc_1.startPoint(), SketchArc_1.startPoint().x(), SketchArc_1.startPoint().y() + 5) +model.end() +model.undo() + +# compare the arc arguments and the resulting shape +aStartAttrY = SketchArc_1.startPoint().y() +aEndAttrX = SketchArc_1.endPoint().x() + +anArcShape = SketchArc_1.feature().lastResult().shape() +aShapeExplorer = GeomAPI_ShapeExplorer(anArcShape, GeomAPI_Shape.VERTEX) + +aPoint = aShapeExplorer.current().vertex().point() +aEndShapeX = aPoint.x() +assert(math.fabs(aEndAttrX - aEndShapeX) < TOLERANCE) + +aShapeExplorer.next() +aPoint = aShapeExplorer.current().vertex().point() +aStartShapeY = aPoint.z() # in 3D sketch y iz Z +assert(math.fabs(aStartAttrY - aStartShapeY) < TOLERANCE) diff --git a/src/SketchSolver/SketchSolver_ConstraintDistance.cpp b/src/SketchSolver/SketchSolver_ConstraintDistance.cpp index 1f827a3c6..b9468ef4a 100644 --- a/src/SketchSolver/SketchSolver_ConstraintDistance.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintDistance.cpp @@ -38,6 +38,41 @@ #include +static void getPointAndLine(const ConstraintPtr& theConstraint, const StoragePtr& theStorage, + EntityWrapperPtr& thePoint, EntityWrapperPtr& theLine) +{ + for (int i = 0; i < 2; ++i) { + AttributePtr anAttr = theConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)); + EntityWrapperPtr anEntity = theStorage->entity(anAttr); + if (anEntity->type() == ENTITY_POINT) + thePoint = anEntity; + else if (anEntity->type() == ENTITY_LINE) + theLine = anEntity; + } +} + +static void adjustOddPoint(const EntityWrapperPtr& theDistPoint, + const EntityWrapperPtr& theDistLine, + GCSPointPtr& theOddPoint) +{ + if (!theOddPoint) + return; + + std::shared_ptr aLine = PlaneGCSSolver_Tools::line(theDistLine); + std::shared_ptr aPoint = PlaneGCSSolver_Tools::point(theDistPoint); + + std::shared_ptr aLineVec = aLine->direction()->xy(); + std::shared_ptr aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy()); + + double aDot = aPtLineVec->dot(aLineVec); + std::shared_ptr aProjectedPnt = + aLine->location()->xy()->added(aLineVec->multiplied(aDot)); + + *(theOddPoint->x) = aProjectedPnt->x(); + *(theOddPoint->y) = aProjectedPnt->y(); +} + + void SketchSolver_ConstraintDistance::getAttributes( EntityWrapperPtr& theValue, std::vector& theAttributes) @@ -67,14 +102,21 @@ void SketchSolver_ConstraintDistance::adjustConstraint() { if (getType() == CONSTRAINT_PT_LINE_DISTANCE) { bool isSigned = myBaseConstraint->boolean(SketchPlugin_ConstraintDistance::SIGNED())->value(); - if (myIsSigned == isSigned) - return; // distance type is not changed => nothing to adjust - - // Adjust point-line distance by setting/removing additional constraints - if (isSigned) - addConstraintsToKeepSign(); - else - removeConstraintsKeepingSign(); + if (myIsSigned == isSigned) { + // adjust auxiliary point for sign-keeping + if (isSigned) { + EntityWrapperPtr aDistPoint, aDistLine; + getPointAndLine(myBaseConstraint, myStorage, aDistPoint, aDistLine); + adjustOddPoint(aDistPoint, aDistLine, myOddPoint); + } + } + else { + // Adjust point-line distance by setting/removing additional constraints + if (isSigned) + addConstraintsToKeepSign(); + else + removeConstraintsKeepingSign(); + } myIsSigned = isSigned; } } @@ -103,14 +145,8 @@ void SketchSolver_ConstraintDistance::addConstraintsToKeepSign() // calculate projection of the point on the line and find a sign of a distance EntityWrapperPtr aDistPoint, aDistLine; - for (int i = 0; i < 2; ++i) { - AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)); - EntityWrapperPtr anEntity = myStorage->entity(anAttr); - if (anEntity->type() == ENTITY_POINT) - aDistPoint = anEntity; - else if (anEntity->type() == ENTITY_LINE) - aDistLine = anEntity; - } + getPointAndLine(myBaseConstraint, myStorage, aDistPoint, aDistLine); + std::shared_ptr aLine = PlaneGCSSolver_Tools::line(aDistLine); std::shared_ptr aPoint = PlaneGCSSolver_Tools::point(aDistPoint); @@ -120,16 +156,12 @@ void SketchSolver_ConstraintDistance::addConstraintsToKeepSign() mySignValue = PI/2.0; else mySignValue = - PI/2.0; - double aDot = aPtLineVec->dot(aLineVec); - std::shared_ptr aProjectedPnt = - aLine->location()->xy()->added(aLineVec->multiplied(aDot)); // create auxiliary point on the line and set auxiliary constraints myOddPoint = GCSPointPtr(new GCS::Point); myOddPoint->x = aStorage->createParameter(); myOddPoint->y = aStorage->createParameter(); - *(myOddPoint->x) = aProjectedPnt->x(); - *(myOddPoint->y) = aProjectedPnt->y(); + adjustOddPoint(aDistPoint, aDistLine, myOddPoint); PointWrapperPtr aPointWr = std::dynamic_pointer_cast(aDistPoint); EdgeWrapperPtr anEdgeWr = std::dynamic_pointer_cast(aDistLine); diff --git a/src/SketchSolver/SketchSolver_Manager.cpp b/src/SketchSolver/SketchSolver_Manager.cpp index 8e976d02b..144fe6c54 100644 --- a/src/SketchSolver/SketchSolver_Manager.cpp +++ b/src/SketchSolver/SketchSolver_Manager.cpp @@ -43,6 +43,42 @@ static bool isFeatureValid(FeaturePtr theFeature) return aFactory->validate(theFeature); } +typedef std::map> IndexedFeatureMap; + +static void featuresOrderedByCreation(const std::set& theOriginalFeatures, + IndexedFeatureMap& theOrderedFeatures) +{ + std::set::iterator aFeatIter = theOriginalFeatures.begin(); + for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) { + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) { + theOrderedFeatures[aFeature->data()->featureId()] = aFeature; + } + } +} + +static void featuresOrderedByType(const std::set& theOriginalFeatures, + IndexedFeatureMap& theOrderedFeatures) +{ + int aFeatureIndex = 0; + int aConstraintIndex = (int)theOriginalFeatures.size(); + + std::set::iterator aFeatIter = theOriginalFeatures.begin(); + for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) { + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) { + std::shared_ptr aConstraint = + std::dynamic_pointer_cast(aFeature); + if (aConstraint) + theOrderedFeatures[++aConstraintIndex] = aFeature; + else + theOrderedFeatures[++aFeatureIndex] = aFeature; + } + } +} + // ======================================================== @@ -115,29 +151,17 @@ void SketchSolver_Manager::processEvent( // update sketch features only const std::set& aFeatures = anUpdateMsg->objects(); + IndexedFeatureMap anOrderedFeatures; // try to keep order as features were created if there are several created features: #2229 if (theMessage->eventID() == aCreatedEvent && aFeatures.size() > 1) { - std::map> anOrderedFeatures; - std::set::iterator aFeatIter; - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - std::shared_ptr aFeature = - std::dynamic_pointer_cast(*aFeatIter); - if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) { - anOrderedFeatures[aFeature->data()->featureId()] = aFeature; - } - } - std::map>::iterator aFeat; - for(aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) { - updateFeature(aFeat->second); - } - } else { // order is not important - std::set::iterator aFeatIter; - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { - std::shared_ptr aFeature = - std::dynamic_pointer_cast(*aFeatIter); - if (aFeature && !aFeature->isMacro()) - updateFeature(aFeature); - } + featuresOrderedByCreation(aFeatures, anOrderedFeatures); + } else { // order is not important, just process features before constraints + featuresOrderedByType(aFeatures, anOrderedFeatures); + } + + IndexedFeatureMap::iterator aFeat; + for (aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) { + updateFeature(aFeat->second); } } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) { -- 2.39.2