From 75998600f27bd4cb25348d871627b313f95fcf35 Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 27 May 2014 10:19:56 +0400 Subject: [PATCH] Small refactoring of SketchSolver. Added SketchSolver_Constraint class to obtain information about constraints --- src/SketchSolver/CMakeLists.txt | 2 + src/SketchSolver/SketchSolver_Constraint.cpp | 192 ++++++++++++++++++ src/SketchSolver/SketchSolver_Constraint.h | 45 ++++ .../SketchSolver_ConstraintManager.cpp | 174 +--------------- .../SketchSolver_ConstraintManager.h | 14 -- src/SketchSolver/SketchSolver_Solver.h | 5 + 6 files changed, 249 insertions(+), 183 deletions(-) create mode 100644 src/SketchSolver/SketchSolver_Constraint.cpp create mode 100644 src/SketchSolver/SketchSolver_Constraint.h diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index 4656f25d5..7c60c7f2e 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -4,11 +4,13 @@ INCLUDE(FindSolveSpace) SET(PROJECT_HEADERS SketchSolver.h SketchSolver_Solver.h + SketchSolver_Constraint.h SketchSolver_ConstraintManager.h ) SET(PROJECT_SOURCES SketchSolver_Solver.cpp + SketchSolver_Constraint.cpp SketchSolver_ConstraintManager.cpp ) diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp new file mode 100644 index 000000000..2bfd8e697 --- /dev/null +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -0,0 +1,192 @@ +// File: SketchSolver_Constraint.cpp +// Created: 27 May 2014 +// Author: Artem ZHIDKOV + +#include "SketchSolver_Constraint.h" +#include + +#include +#include + +#include +#include + + +SketchSolver_Constraint::SketchSolver_Constraint() + : myConstraint(boost::shared_ptr()), + myType(SLVS_C_UNKNOWN), + myAttributesList() +{ +} + +SketchSolver_Constraint::SketchSolver_Constraint( + boost::shared_ptr theConstraint) + : myConstraint(theConstraint), + myAttributesList() +{ + myType = getType(myConstraint); +} + +const int& SketchSolver_Constraint::getType(boost::shared_ptr theConstraint) +{ + myType = SLVS_C_UNKNOWN; + if (!theConstraint) + return getType(); + + // Assign empty names of attributes + myAttributesList.clear(); + for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++) + myAttributesList.push_back(std::string()); + + const std::string& aConstraintKind = theConstraint->getKind(); + // Constraint for coincidence of two points + if (aConstraintKind.compare("SketchConstraintCoincidence") == 0) + { + int anAttrPos = 0; + // Verify the constraint has only two attributes and they are points + int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point + int aPt3d = 0; // bit-mapped field, the same information for 3D points + for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) + { + boost::shared_ptr anAttr = + boost::dynamic_pointer_cast( + theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) + ); + if (!anAttr) continue; + // Verify the attribute is a 2D point + boost::shared_ptr aPoint2D = + boost::dynamic_pointer_cast(anAttr->attr()); + if (aPoint2D) + { + aPt2d |= (1 << indAttr); + myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + // Verify the attribute is a 3D point + boost::shared_ptr aPoint3D = + boost::dynamic_pointer_cast(anAttr->attr()); + if (aPoint3D) + { + aPt3d |= (1 << indAttr); + myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + // Attribute neither 2D nor 3D point is not supported by this type of constraint + return getType(); + } + // The constrained points should be in first and second positions, + // so the expected value of aPt2d or aPt3d is 3 + if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3)) + myType = SLVS_C_POINTS_COINCIDENT; + // Constraint parameters are wrong + return getType(); + } + + // Constraint for distance between point and another entity + if (aConstraintKind.compare("SketchConstraintDistance") == 0) + { + int aNbPoints = 0; + int aNbEntities = 0; + for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) + { + boost::shared_ptr anAttr = + boost::dynamic_pointer_cast( + theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) + ); + if (!anAttr) continue; + if (anAttr->isFeature()) + { // verify posiible entities + const std::string& aKind = anAttr->feature()->getKind(); + if (aKind.compare("SketchPoint") == 0) + { + myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + else if(aKind.compare("SketchLine") == 0) + { + // entities are placed starting from CONSTRAINT_ATTR_ENTITY_C attribute + myAttributesList[2 + aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; + myType = SLVS_C_PT_LINE_DISTANCE; + continue; + } + } + else + { // verify points + // Verify the attribute is a 2D point + boost::shared_ptr aPoint2D = + boost::dynamic_pointer_cast(anAttr->attr()); + if (aPoint2D) + { + myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + // Verify the attribute is a 3D point + boost::shared_ptr aPoint3D = + boost::dynamic_pointer_cast(anAttr->attr()); + if (aPoint3D) + { + myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + } + } + // Verify the correctness of constraint arguments + if (aNbPoints == 2 && aNbEntities ==0) + myType = SLVS_C_PT_PT_DISTANCE; + else if (aNbPoints == 1 && aNbEntities == 1) + myType = SLVS_C_UNKNOWN; + return getType(); + } + + // Constraint for two parallel/perpendicular lines + bool isParallel = (aConstraintKind.compare("SketchConstraintParallel") == 0); + bool isPerpendicular = (aConstraintKind.compare("SketchConstraintPerpendicular") == 0); + if (isParallel || isPerpendicular) + { + int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute + for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) + { + boost::shared_ptr anAttr = + boost::dynamic_pointer_cast( + theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) + ); + if (!anAttr || !anAttr->isFeature()) continue; + const std::string& aKind = anAttr->feature()->getKind(); + if (aKind.compare("SketchLine") == 0) + { + myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + } + if (aNbEntities == 4) + myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR; + return getType(); + } + + // Constraint for diameter of a circle + if (aConstraintKind.compare("SketchConstraintDiameter") == 0) + { + int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute + for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) + { + boost::shared_ptr anAttr = + boost::dynamic_pointer_cast( + theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) + ); + if (!anAttr || !anAttr->isFeature()) continue; + const std::string& aKind = anAttr->feature()->getKind(); + if (aKind.compare("SketchCircle") == 0) + { + myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; + continue; + } + } + if (aNbEntities == 3) + myType = SLVS_C_DIAMETER; + return getType(); + } + + /// \todo Implement other kind of constrtaints + + return getType(); +} diff --git a/src/SketchSolver/SketchSolver_Constraint.h b/src/SketchSolver/SketchSolver_Constraint.h new file mode 100644 index 000000000..934415b34 --- /dev/null +++ b/src/SketchSolver/SketchSolver_Constraint.h @@ -0,0 +1,45 @@ +// File: SketchSolver_Constraint.h +// Created: 27 May 2014 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_Constraint_Headerfile +#define SketchSolver_Constraint_Headerfile + +#include "SketchSolver.h" + +#include + +#include +#include + +/** \class SketchSolver_Constraint + * \ingroup DataModel + * \brief Obtain information about SketchPlugin's constraint + */ +class SketchSolver_Constraint +{ +public: + SketchSolver_Constraint(); + SketchSolver_Constraint(boost::shared_ptr theConstraint); + + /** \brief Compute constraint type according to SolveSpace identifiers + * and verify that constraint parameters are correct + * \param[in] theConstraint constraint which type should be determined + * \return identifier of constraint type or SLVS_C_UNKNOWN if the type is wrong + */ + const int& getType(boost::shared_ptr theConstraint); + /// \brief Returns the type of myConstraint member + inline const int& getType() const + { return myType; } + + /// \brief Returns list of attributes names in the correct order required by SolveSpace + inline const std::vector& getAttributes() const + { return myAttributesList; } + +private: + boost::shared_ptr myConstraint; + int myType; + std::vector myAttributesList; +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index c02da61a7..4fd5b4f07 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -4,6 +4,8 @@ #include "SketchSolver_ConstraintManager.h" +#include + #include #include #include @@ -483,11 +485,12 @@ bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::changeConstra } // Get constraint type and verify the constraint parameters are correct - std::vector aConstraintAttributes; - int aConstrType = getConstraintType(theConstraint, aConstraintAttributes); + SketchSolver_Constraint aConstraint(theConstraint); + int aConstrType = aConstraint.getType(); if (aConstrType == SLVS_C_UNKNOWN || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType)) return false; + const std::vector& aConstraintAttributes = aConstraint.getAttributes(); // Create constraint parameters double aDistance = 0.0; // scalar value of the constraint @@ -812,173 +815,6 @@ Slvs_hParam SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::change return aParam.h; } -// ============================================================================ -// Function: getConstraintType -// Class: SketchSolver_ConstraintGroup -// Purpose: calculate the type of constraint using its parameters -// ============================================================================ -int SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::getConstraintType( - const boost::shared_ptr& theConstraint, - std::vector& theAttrNames) const -{ - // Assign empty names of attributes - for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++) - theAttrNames.push_back(std::string()); - - const std::string& aConstraintKind = theConstraint->getKind(); - // Constraint for coincidence of two points - if (aConstraintKind.compare("SketchConstraintCoincidence") == 0) - { - int anAttrPos = 0; - // Verify the constraint has only two attributes and they are points - int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point - int aPt3d = 0; // bit-mapped field, the same information for 3D points - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr) continue; - // Verify the attribute is a 2D point - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint2D) - { - aPt2d |= (1 << indAttr); - theAttrNames[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - // Verify the attribute is a 3D point - boost::shared_ptr aPoint3D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint3D) - { - aPt3d |= (1 << indAttr); - theAttrNames[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - // Attribute neither 2D nor 3D point is not supported by this type of constraint - return SLVS_C_UNKNOWN; - } - // The constrained points should be in first and second positions, - // so the expected value of aPt2d or aPt3d is 3 - if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3)) - return SLVS_C_POINTS_COINCIDENT; - // Constraint parameters are wrong - return SLVS_C_UNKNOWN; - } - - // Constraint for distance between point and another entity - if (aConstraintKind.compare("SketchConstraintDistance") == 0) - { - int aResult = SLVS_C_UNKNOWN; // possible constraint type - int aNbPoints = 0; - int aNbEntities = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr) continue; - if (anAttr->isFeature()) - { // verify posiible entities - const std::string& aKind = anAttr->feature()->getKind(); - if (aKind.compare("SketchPoint") == 0) - { - theAttrNames[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - else if(aKind.compare("SketchLine") == 0) - { - // entities are placed starting from CONSTRAINT_ATTR_ENTITY_C attribute - theAttrNames[2 + aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; - aResult = SLVS_C_PT_LINE_DISTANCE; - continue; - } - } - else - { // verify points - // Verify the attribute is a 2D point - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint2D) - { - theAttrNames[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - // Verify the attribute is a 3D point - boost::shared_ptr aPoint3D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint3D) - { - theAttrNames[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - } - } - // Verify the correctness of constraint arguments - if (aNbPoints == 2 && aNbEntities ==0) - aResult = SLVS_C_PT_PT_DISTANCE; - else if (aNbPoints == 1 && aNbEntities == 1) - aResult = SLVS_C_UNKNOWN; - return aResult; - } - - // Constraint for two parallel/perpendicular lines - bool isParallel = (aConstraintKind.compare("SketchConstraintParallel") == 0); - bool isPerpendicular = (aConstraintKind.compare("SketchConstraintPerpendicular") == 0); - if (isParallel || isPerpendicular) - { - int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr || !anAttr->isFeature()) continue; - const std::string& aKind = anAttr->feature()->getKind(); - if (aKind.compare("SketchLine") == 0) - { - theAttrNames[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - } - if (aNbEntities == 4) - return isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR; - return SLVS_C_UNKNOWN; - } - - // Constraint for diameter of a circle - if (aConstraintKind.compare("SketchConstraintDiameter") == 0) - { - int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr || !anAttr->isFeature()) continue; - const std::string& aKind = anAttr->feature()->getKind(); - if (aKind.compare("SketchCircle") == 0) - { - theAttrNames[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - } - if (aNbEntities == 3) - return SLVS_C_DIAMETER; - return SLVS_C_UNKNOWN; - } - - /// \todo Implement other kind of constrtaints - - return SLVS_C_UNKNOWN; -} - // ============================================================================ // Function: resolveConstraints // Class: SketchSolver_ConstraintGroup diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.h b/src/SketchSolver/SketchSolver_ConstraintManager.h index 5bbfe2f69..548d20f10 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.h +++ b/src/SketchSolver/SketchSolver_ConstraintManager.h @@ -20,11 +20,6 @@ #include -// Unknown constraint (for error reporting) -#define SLVS_C_UNKNOWN 0 -// Unknown entity -#define SLVS_E_UNKNOWN 0 - /** \class SketchSolver_ConstraintManager * \ingroup DataModel * \brief Listens the changes of SketchPlugin features and transforms the Constraint @@ -216,15 +211,6 @@ protected: Slvs_hParam changeParameter(const double& theParam, std::vector::const_iterator& thePrmIter); - /** \brief Compute constraint type according to SolveSpace identifiers - * and verify that constraint parameters are correct - * \param[in] theConstraint constraint which type should be determined - * \param[out] theAttrNames names of attributes in order required by SolveSpace (unused attributes have empty names) - * \return identifier of constraint type or SLVS_C_UNKNOWN if the type is wrong - */ - int getConstraintType(const boost::shared_ptr& theConstraint, - std::vector& theAttrNames) const; - /** \brief Change values of attribute by parameters received from SolveSpace solver * \param[in,out] theAttribute pointer to the attribute to be changed * \param[in] theEntityID identifier of SolveSpace entity, which contains updated data diff --git a/src/SketchSolver/SketchSolver_Solver.h b/src/SketchSolver/SketchSolver_Solver.h index 944a58e69..19408410a 100644 --- a/src/SketchSolver/SketchSolver_Solver.h +++ b/src/SketchSolver/SketchSolver_Solver.h @@ -21,6 +21,11 @@ typedef unsigned int UINT32; #define SLVS_RESULT_EMPTY_SET -1 +// Unknown constraint (for error reporting) +#define SLVS_C_UNKNOWN 0 +// Unknown entity +#define SLVS_E_UNKNOWN 0 + class SketchSolver_Solver { -- 2.39.2