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.
Test2711.py
Test2741.py
Test2810.py
+ Test2824.py
TestArcBehavior.py
TestConstraintAngle.py
TestConstraintCoincidence.py
--- /dev/null
+## 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<mailto: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)
#include <math.h>
+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<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(theDistLine);
+ std::shared_ptr<GeomAPI_Pnt2d> aPoint = PlaneGCSSolver_Tools::point(theDistPoint);
+
+ std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+ std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+
+ double aDot = aPtLineVec->dot(aLineVec);
+ std::shared_ptr<GeomAPI_XY> aProjectedPnt =
+ aLine->location()->xy()->added(aLineVec->multiplied(aDot));
+
+ *(theOddPoint->x) = aProjectedPnt->x();
+ *(theOddPoint->y) = aProjectedPnt->y();
+}
+
+
void SketchSolver_ConstraintDistance::getAttributes(
EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
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;
}
}
// 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<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(aDistLine);
std::shared_ptr<GeomAPI_Pnt2d> aPoint = PlaneGCSSolver_Tools::point(aDistPoint);
mySignValue = PI/2.0;
else
mySignValue = - PI/2.0;
- double aDot = aPtLineVec->dot(aLineVec);
- std::shared_ptr<GeomAPI_XY> 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<PlaneGCSSolver_PointWrapper>(aDistPoint);
EdgeWrapperPtr anEdgeWr = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aDistLine);
return aFactory->validate(theFeature);
}
+typedef std::map<int, std::shared_ptr<SketchPlugin_Feature>> IndexedFeatureMap;
+
+static void featuresOrderedByCreation(const std::set<ObjectPtr>& theOriginalFeatures,
+ IndexedFeatureMap& theOrderedFeatures)
+{
+ std::set<ObjectPtr>::iterator aFeatIter = theOriginalFeatures.begin();
+ for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) {
+ std::shared_ptr<SketchPlugin_Feature> aFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
+ theOrderedFeatures[aFeature->data()->featureId()] = aFeature;
+ }
+ }
+}
+
+static void featuresOrderedByType(const std::set<ObjectPtr>& theOriginalFeatures,
+ IndexedFeatureMap& theOrderedFeatures)
+{
+ int aFeatureIndex = 0;
+ int aConstraintIndex = (int)theOriginalFeatures.size();
+
+ std::set<ObjectPtr>::iterator aFeatIter = theOriginalFeatures.begin();
+ for (; aFeatIter != theOriginalFeatures.end(); aFeatIter++) {
+ std::shared_ptr<SketchPlugin_Feature> aFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
+ std::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ std::dynamic_pointer_cast<SketchPlugin_Constraint>(aFeature);
+ if (aConstraint)
+ theOrderedFeatures[++aConstraintIndex] = aFeature;
+ else
+ theOrderedFeatures[++aFeatureIndex] = aFeature;
+ }
+ }
+}
+
// ========================================================
// update sketch features only
const std::set<ObjectPtr>& 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<int, std::shared_ptr<SketchPlugin_Feature>> anOrderedFeatures;
- std::set<ObjectPtr>::iterator aFeatIter;
- for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (aFeature && !aFeature->isMacro() && aFeature->data() && aFeature->data()->isValid()) {
- anOrderedFeatures[aFeature->data()->featureId()] = aFeature;
- }
- }
- std::map<int, std::shared_ptr<SketchPlugin_Feature>>::iterator aFeat;
- for(aFeat = anOrderedFeatures.begin(); aFeat != anOrderedFeatures.end(); aFeat++) {
- updateFeature(aFeat->second);
- }
- } else { // order is not important
- std::set<ObjectPtr>::iterator aFeatIter;
- for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(*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)) {