From 964cad2613a9a40164fcdac4fc62c73a65244465 Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 13 Feb 2019 15:14:57 +0300 Subject: [PATCH] Issues #2850, #2860: Change type of angle while Python Dump, because the configuration of constrained lines may be changed by the subsequent constraints. --- .../ModelHighAPI_FeatureStore.cpp | 15 ++ src/SketchAPI/CMakeLists.txt | 2 + src/SketchAPI/SketchAPI.i | 2 + src/SketchAPI/SketchAPI_Constraint.cpp | 45 +++--- src/SketchAPI/SketchAPI_Constraint.h | 5 + src/SketchAPI/SketchAPI_ConstraintAngle.cpp | 134 ++++++++++++++++++ src/SketchAPI/SketchAPI_ConstraintAngle.h | 51 +++++++ src/SketchAPI/SketchAPI_swig.h | 1 + src/SketchPlugin/CMakeLists.txt | 1 + src/SketchPlugin/Test/Test2860.py | 42 ++++++ 10 files changed, 272 insertions(+), 26 deletions(-) create mode 100644 src/SketchAPI/SketchAPI_ConstraintAngle.cpp create mode 100644 src/SketchAPI/SketchAPI_ConstraintAngle.h create mode 100644 src/SketchPlugin/Test/Test2860.py diff --git a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp index b1feda567..db86c56cb 100644 --- a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp +++ b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp @@ -188,12 +188,23 @@ std::string ModelHighAPI_FeatureStore::dumpAttr(const AttributePtr& theAttr) { } } else if (aType == ModelAPI_AttributeInteger::typeId()) { AttributeIntegerPtr anAttr = std::dynamic_pointer_cast(theAttr); + // do not dump a type of ConstraintAngle, because it can be changed due dumping + if (anAttr->id() == "AngleType") { + return ""; + } if (anAttr->text().empty()) aResult<value(); else aResult<text(); } else if (aType == ModelAPI_AttributeDouble::typeId()) { AttributeDoublePtr anAttr = std::dynamic_pointer_cast(theAttr); + if (anAttr->id() == "ConstraintValue") { + // do not dump a value of constraint if it is ConstraintAngle, + // because this value depends on the angle type + FeaturePtr anOwner = ModelAPI_Feature::feature(anAttr->owner()); + if (anOwner && anOwner->getKind() == "SketchConstraintAngle") + return ""; + } int aPrecision = PRECISION; // Special case - precision for the arc angle. It is calculated with tolerance 1e-4, // so the value has only 4 correct digits @@ -206,6 +217,10 @@ std::string ModelHighAPI_FeatureStore::dumpAttr(const AttributePtr& theAttr) { aResult<text(); } else if (aType == ModelAPI_AttributeBoolean::typeId()) { AttributeBooleanPtr anAttr = std::dynamic_pointer_cast(theAttr); + // do not dump internal flags of ConstraintAngle + if (anAttr->id() == "AngleReversedLine1" || anAttr->id() == "AngleReversedLine2") { + return ""; + } aResult<value(); } else if (aType == ModelAPI_AttributeString::typeId()) { AttributeStringPtr anAttr = std::dynamic_pointer_cast(theAttr); diff --git a/src/SketchAPI/CMakeLists.txt b/src/SketchAPI/CMakeLists.txt index 389d004e7..ac3b1364c 100644 --- a/src/SketchAPI/CMakeLists.txt +++ b/src/SketchAPI/CMakeLists.txt @@ -25,6 +25,7 @@ SET(PROJECT_HEADERS SketchAPI_Arc.h SketchAPI_Circle.h SketchAPI_Constraint.h + SketchAPI_ConstraintAngle.h SketchAPI_IntersectionPoint.h SketchAPI_Line.h SketchAPI_MacroArc.h @@ -43,6 +44,7 @@ SET(PROJECT_SOURCES SketchAPI_Arc.cpp SketchAPI_Circle.cpp SketchAPI_Constraint.cpp + SketchAPI_ConstraintAngle.cpp SketchAPI_IntersectionPoint.cpp SketchAPI_Line.cpp SketchAPI_MacroArc.cpp diff --git a/src/SketchAPI/SketchAPI.i b/src/SketchAPI/SketchAPI.i index 0f76546eb..23a3506fb 100644 --- a/src/SketchAPI/SketchAPI.i +++ b/src/SketchAPI/SketchAPI.i @@ -50,6 +50,7 @@ %shared_ptr(SketchAPI_Circle) %shared_ptr(SketchAPI_MacroCircle) %shared_ptr(SketchAPI_Constraint) +%shared_ptr(SketchAPI_ConstraintAngle) %shared_ptr(SketchAPI_IntersectionPoint) %shared_ptr(SketchAPI_Line) %shared_ptr(SketchAPI_Mirror) @@ -239,3 +240,4 @@ %include "SketchAPI_Rotation.h" %include "SketchAPI_Sketch.h" %include "SketchAPI_Constraint.h" +%include "SketchAPI_ConstraintAngle.h" diff --git a/src/SketchAPI/SketchAPI_Constraint.cpp b/src/SketchAPI/SketchAPI_Constraint.cpp index d9edb13de..dd15059ec 100644 --- a/src/SketchAPI/SketchAPI_Constraint.cpp +++ b/src/SketchAPI/SketchAPI_Constraint.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -97,10 +96,6 @@ static const std::string& constraintTypeToSetter(const std::string& theType) static const std::string COINCIDENCE_SETTER("setCoincident"); return COINCIDENCE_SETTER; } - if (theType == SketchPlugin_ConstraintAngle::ID()) { - static const std::string ANGLE_SETTER("setAngle"); - return ANGLE_SETTER; - } if (theType == SketchPlugin_ConstraintCollinear::ID()) { static const std::string COLLINEAR_SETTER("setCollinear"); return COLLINEAR_SETTER; @@ -175,6 +170,20 @@ static std::string angleTypeToString(int theAngleType) return std::string(); } +bool SketchAPI_Constraint::areAllAttributesDumped(ModelHighAPI_Dumper& theDumper) const +{ + bool areAttributesDumped = true; + FeaturePtr aBase = feature(); + for (int i = 0; i < CONSTRAINT_ATTR_SIZE && areAttributesDumped; ++i) { + AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + if (aRefAttr && aRefAttr->isInitialized()) + areAttributesDumped = theDumper.isDumped(aRefAttr); + } + if (!areAttributesDumped) + theDumper.postpone(aBase); + return areAttributesDumped; +} + void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const { FeaturePtr aBase = feature(); @@ -194,26 +203,12 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const return; } - // Check all attributes are already dumped. If not, store the constraint as postponed. - bool areAttributesDumped = true; - for (int i = 0; i < CONSTRAINT_ATTR_SIZE && areAttributesDumped; ++i) { - AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); - if (aRefAttr && aRefAttr->isInitialized()) - areAttributesDumped = theDumper.isDumped(aRefAttr); - } - if (!areAttributesDumped) { - theDumper.postpone(aBase); + // postpone constraint until all its attributes be dumped + if (!areAllAttributesDumped(theDumper)) return; - } - - bool isAngle = aBase->getKind() == SketchPlugin_ConstraintAngle::ID(); - std::string aSetterSuffix; - if (isAngle) - aSetterSuffix = angleTypeToString(aBase->integer( - SketchPlugin_ConstraintAngle::TYPE_ID())->value()); const std::string& aSketchName = theDumper.parentName(aBase); - theDumper << aBase << " = " << aSketchName << "." << aSetter << aSetterSuffix << "("; + theDumper << aBase << " = " << aSketchName << "." << aSetter << "("; bool isFirstAttr = true; for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { @@ -225,10 +220,8 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const } AttributeDoublePtr aValueAttr; - if (isAngle) - aValueAttr = aBase->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()); - else if (aBase->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() || - aBase->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) + if (aBase->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() || + aBase->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) aValueAttr = aBase->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()); else aValueAttr = aBase->real(SketchPlugin_Constraint::VALUE()); diff --git a/src/SketchAPI/SketchAPI_Constraint.h b/src/SketchAPI/SketchAPI_Constraint.h index 958bbdae3..892deec76 100644 --- a/src/SketchAPI/SketchAPI_Constraint.h +++ b/src/SketchAPI/SketchAPI_Constraint.h @@ -66,6 +66,11 @@ public: /// Dump wrapped feature SKETCHAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const; + +protected: + // Check all attributes of constraint are already dumped. + // If not, store the constraint as postponed. + bool areAllAttributesDumped(ModelHighAPI_Dumper& theDumper) const; }; #endif diff --git a/src/SketchAPI/SketchAPI_ConstraintAngle.cpp b/src/SketchAPI/SketchAPI_ConstraintAngle.cpp new file mode 100644 index 000000000..cdfa37b6d --- /dev/null +++ b/src/SketchAPI/SketchAPI_ConstraintAngle.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2019-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 +// + +#include "SketchAPI_ConstraintAngle.h" + +#include +#include + +#include +#include + +#include +#include + +#include + +SketchAPI_ConstraintAngle::SketchAPI_ConstraintAngle( + const std::shared_ptr & theFeature) +: SketchAPI_Constraint(theFeature) +{ + ConstraintPtr aConstraint = std::dynamic_pointer_cast(theFeature); + if (aConstraint) + initialize(); +} + +static FeaturePtr getFeatureLine(DataPtr theData, const std::string& theAttribute) +{ + FeaturePtr aLine; + if (!theData.get() || !theData->isValid()) /// essential check as it is called in openGl thread) + return aLine; + + std::shared_ptr anAttr = + std::dynamic_pointer_cast(theData->attribute(theAttribute)); + if (anAttr) { + FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object()); + if (aFeature && aFeature->getKind() == SketchPlugin_Line::ID()) { + return aFeature; + } + } + return aLine; +} + +static void calculatePossibleValuesOfAngle(FeaturePtr theFeature, + double& theAngleDirect, double& theAngleComplementary, double& theAngleBackward) +{ + std::shared_ptr aData = theFeature->data(); + FeaturePtr aLineA = getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A()); + FeaturePtr aLineB = getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B()); + + std::shared_ptr aStartA = std::dynamic_pointer_cast( + aLineA->attribute(SketchPlugin_Line::START_ID())); + std::shared_ptr aEndA = std::dynamic_pointer_cast( + aLineA->attribute(SketchPlugin_Line::END_ID())); + std::shared_ptr aStartB = std::dynamic_pointer_cast( + aLineB->attribute(SketchPlugin_Line::START_ID())); + std::shared_ptr aEndB = std::dynamic_pointer_cast( + aLineB->attribute(SketchPlugin_Line::END_ID())); + + std::shared_ptr anAng(new GeomAPI_Angle2d( + aStartA->pnt(), aEndA->pnt(), aStartB->pnt(), aEndB->pnt())); + theAngleDirect = anAng->angleDegree(); + theAngleBackward = 360.0 - theAngleDirect; + + if (theAngleDirect > 180.0) + theAngleComplementary = theAngleDirect - 180.0; + else + theAngleComplementary = 180.0 - theAngleDirect; +} + +static std::string angleTypeToString(FeaturePtr theFeature) +{ + static const double TOLERANCE = 1.e-7; + double anAngleDirect, anAngleComplmentary, anAngleBackward; + calculatePossibleValuesOfAngle(theFeature, anAngleDirect, anAngleComplmentary, anAngleBackward); + + AttributeDoublePtr aValueAttr = theFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()); + + std::string aType; + if (fabs(aValueAttr->value() - anAngleDirect) < TOLERANCE) { + // Nothing to do. + // This case is empty and going the first to check the direct angle before the others. + } + else if (fabs(aValueAttr->value() - anAngleComplmentary) < TOLERANCE) + aType = "Complementary"; + else if (fabs(aValueAttr->value() - anAngleBackward) < TOLERANCE) + aType = "Backward"; + return aType; +} + +void SketchAPI_ConstraintAngle::dump(ModelHighAPI_Dumper& theDumper) const +{ + // postpone constraint until all its attributes be dumped + if (!areAllAttributesDumped(theDumper)) + return; + + // calculate angle value as it was just applied to the attributes + FeaturePtr aBase = feature(); + std::string aSetterSuffix = angleTypeToString(aBase); + + const std::string& aSketchName = theDumper.parentName(aBase); + theDumper << aBase << " = " << aSketchName << "." << "setAngle" << aSetterSuffix << "("; + + bool isFirstAttr = true; + for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { + AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + if (aRefAttr && aRefAttr->isInitialized()) { + theDumper << (isFirstAttr ? "" : ", ") << aRefAttr; + isFirstAttr = false; + } + } + + AttributeDoublePtr aValueAttr = aBase->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()); + if (aValueAttr && aValueAttr->isInitialized()) + theDumper << ", " << aValueAttr; + + theDumper << ")" << std::endl; +} diff --git a/src/SketchAPI/SketchAPI_ConstraintAngle.h b/src/SketchAPI/SketchAPI_ConstraintAngle.h new file mode 100644 index 000000000..573d2013b --- /dev/null +++ b/src/SketchAPI/SketchAPI_ConstraintAngle.h @@ -0,0 +1,51 @@ +// Copyright (C) 2019-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 +// + +#ifndef SRC_SKETCHAPI_SKETCHAPI_CONSTRAINTANGLE_H_ +#define SRC_SKETCHAPI_SKETCHAPI_CONSTRAINTANGLE_H_ + +#include "SketchAPI_Constraint.h" + +class ModelHighAPI_Double; + +/**\class SketchAPI_ConstraintAngle + * \ingroup CPPHighAPI + * \brief Interface for ConstraintAngle feature + */ +class SketchAPI_ConstraintAngle : public SketchAPI_Constraint +{ +public: + /// Constructor without values + SKETCHAPI_EXPORT + explicit SketchAPI_ConstraintAngle(const std::shared_ptr & theFeature); + + static std::string ID() + { + static const std::string MY_SKETCH_CONSTRAINT_ID = "SketchConstraintAngle"; + return MY_SKETCH_CONSTRAINT_ID; + } + virtual std::string getID() { return ID(); } + + /// Dump wrapped feature + SKETCHAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; +}; + +#endif diff --git a/src/SketchAPI/SketchAPI_swig.h b/src/SketchAPI/SketchAPI_swig.h index 440eb2aec..1b6e81f3c 100644 --- a/src/SketchAPI/SketchAPI_swig.h +++ b/src/SketchAPI/SketchAPI_swig.h @@ -29,6 +29,7 @@ #include "SketchAPI_Circle.h" #include "SketchAPI_MacroCircle.h" #include "SketchAPI_Constraint.h" + #include "SketchAPI_ConstraintAngle.h" #include "SketchAPI_IntersectionPoint.h" #include "SketchAPI_Line.h" #include "SketchAPI_Mirror.h" diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index dad15e6d7..7c49a07fc 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -193,6 +193,7 @@ ADD_UNIT_TESTS( Test2741.py Test2810.py Test2824.py + Test2860.py TestArcBehavior.py TestConstraintAngle.py TestConstraintCoincidence.py diff --git a/src/SketchPlugin/Test/Test2860.py b/src/SketchPlugin/Test/Test2860.py new file mode 100644 index 000000000..d497c8d21 --- /dev/null +++ b/src/SketchPlugin/Test/Test2860.py @@ -0,0 +1,42 @@ +## 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 +## + +""" + Test2860.py + Test case for issue #2650 "setAngleComplementary becomes setAngle in BARCOM" + Test case for issue #2860 "Error in python dump reload because of setAngleComplementary" +""" + +from salome.shaper import model +from SketchAPI import * + +model.begin() +partSet = model.moduleDocument() +Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-9.326798599059195, -0.7578903795715272, 33.09960827213365, 41.66851649162133) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 60) +SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "OY"), False) +SketchLine_2 = SketchProjection_1.createdFeature() +SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_1.result(), SketchLine_2.result(), 45) +SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Line(SketchLine_2).startPoint(), SketchLine_1.endPoint(), 5) +model.do() +model.end() + +assert(model.checkPythonDump()) -- 2.39.2