From d56fb361cb3725fbf72b3d6c5a152652b83ab463 Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 13 May 2014 08:27:27 +0400 Subject: [PATCH] Base class for constraints was updated. Constraint manager functionality was started. --- src/SketchPlugin/SketchPlugin_Constraint.cpp | 27 +++ src/SketchPlugin/SketchPlugin_Constraint.h | 19 +- .../SketchPlugin_ConstraintDistance.h | 2 +- src/SketchSolver/CMakeLists.txt | 6 +- .../SketchSolver_ConstraintManager.cpp | 188 ++++++++++++++++++ .../SketchSolver_ConstraintManager.h | 110 ++++++++++ 6 files changed, 348 insertions(+), 4 deletions(-) diff --git a/src/SketchPlugin/SketchPlugin_Constraint.cpp b/src/SketchPlugin/SketchPlugin_Constraint.cpp index 810f0c9ec..6269e3213 100644 --- a/src/SketchPlugin/SketchPlugin_Constraint.cpp +++ b/src/SketchPlugin/SketchPlugin_Constraint.cpp @@ -4,12 +4,39 @@ #include "SketchPlugin_Constraint.h" +#include +#include + +const boost::shared_ptr& SketchPlugin_Constraint::preview() +{ + return getPreview(); +} + void SketchPlugin_Constraint::addConstrainedObject( + const std::string& theAttrID, const boost::shared_ptr& theReference) { + if (!data()->attribute(theAttrID).get()) + data()->addAttribute(theAttrID, theReference->type()); + boost::dynamic_pointer_cast( + data()->attribute(theAttrID))->setValue(theReference->value()); } void SketchPlugin_Constraint::addConstrainedObject( + const std::string& theAttrID, const boost::shared_ptr& theReference) { + if (!data()->attribute(theAttrID).get()) + data()->addAttribute(theAttrID, theReference->type()); + boost::dynamic_pointer_cast( + data()->attribute(theAttrID))->setValue(theReference->value()); +} + +void SketchPlugin_Constraint::getSketchParameters( + std::list< boost::shared_ptr >& theParams) +{ + theParams.push_back(sketch()->data()->attribute(SKETCH_ATTR_ORIGIN)); + theParams.push_back(sketch()->data()->attribute(SKETCH_ATTR_DIRX)); + theParams.push_back(sketch()->data()->attribute(SKETCH_ATTR_DIRY)); + theParams.push_back(sketch()->data()->attribute(SKETCH_ATTR_NORM)); } diff --git a/src/SketchPlugin/SketchPlugin_Constraint.h b/src/SketchPlugin/SketchPlugin_Constraint.h index 031587be0..9a5e9e480 100644 --- a/src/SketchPlugin/SketchPlugin_Constraint.h +++ b/src/SketchPlugin/SketchPlugin_Constraint.h @@ -49,6 +49,11 @@ public: SKETCHPLUGIN_EXPORT virtual const std::string& getGroup() {static std::string MY_GROUP = "Sketch"; return MY_GROUP;} + /// Returns the sketch preview + /// \param theSketch the owner of this feature + /// \return the built preview + SKETCHPLUGIN_EXPORT virtual const boost::shared_ptr& preview(); + /** \brief Adds sub-feature of the higher level feature (sub-element of the sketch) * \param theFeature sub-feature */ @@ -56,17 +61,27 @@ public: const boost::shared_ptr& theFeature) {} /** \brief Adds an object of the constraint. The object added by the reference. - * \param theReference reference to the feature, which will be constrained + * \param[in] theAttrID identifier of the attribute + * \param[in] theReference reference to the feature, which will be constrained */ SKETCHPLUGIN_EXPORT virtual void addConstrainedObject( + const std::string& theAttrID, const boost::shared_ptr& theReference); /** \brief Adds an object of the constraint. The object added by the reference to its attribute. - * \param theReference reference to the attribute feature, which will be constrained + * \param[in] theAttrID identifier of the attribute + * \param[in] theReference reference to the attribute feature, which will be constrained */ SKETCHPLUGIN_EXPORT virtual void addConstrainedObject( + const std::string& theAttrID, const boost::shared_ptr& theReference); + /** \brief Prepares list of attributes of current sketch workplane + * \param[out] theParams list of attributes + */ + SKETCHPLUGIN_EXPORT void getSketchParameters( + std::list< boost::shared_ptr >& theParams); + /// \brief Use plugin manager for features creation SketchPlugin_Constraint() {} diff --git a/src/SketchPlugin/SketchPlugin_ConstraintDistance.h b/src/SketchPlugin/SketchPlugin_ConstraintDistance.h index 0199e4ef3..48b59e1ed 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintDistance.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintDistance.h @@ -54,7 +54,7 @@ public: { /* do nothing */ } /// \brief Use plugin manager for features creation - SketchPlugin_ConstraintDistance(); + SKETCHPLUGIN_EXPORT SketchPlugin_ConstraintDistance(); /** \brief Initializes the attributes of the constraint * diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index c26ddc829..5d04a4a95 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -17,10 +17,14 @@ SET(PROJECT_LIBRARIES SketchPlugin ) -SET(INCLUDE_DIRECTORIES +INCLUDE_DIRECTORIES( ../SketchPlugin + ../ModelAPI + ../GeomAPI ) +ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS ${BOOST_DEFINITIONS}) + ADD_LIBRARY(SketchSolver SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index d8d3b5f98..86cb8bacd 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -3,3 +3,191 @@ // Author: Artem ZHIDKOV #include "SketchSolver_ConstraintManager.h" + +#include +#include +#include +#include +#include + + +/// This value is used to give unique index to the groups +static Slvs_hGroup myGroupIndexer = 0; + +// ======================================================== +// ========= SketchSolver_ConstraintManager =============== +// ======================================================== +SketchSolver_ConstraintManager::SketchSolver_ConstraintManager() +{ + myGroups.clear(); +} + +SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager() +{ + myGroups.clear(); +} + +void SketchSolver_ConstraintManager::findGroups( + boost::shared_ptr theConstraint, + std::vector& theGroupIDs) const +{ + std::vector::const_iterator aGroupIter; + for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) + if (aGroupIter->isInteract(theConstraint)) + theGroupIDs.push_back(aGroupIter->getId()); +} + + +// ======================================================== +// ========= SketchSolver_ConstraintGroup =============== +// ======================================================== + +SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::SketchSolver_ConstraintGroup() + : myID(++myGroupIndexer), + myParamMaxID(0), + myEntityMaxID(0), + myConstrMaxID(0), + myConstraintMap() +{ + myParams.clear(); + myEntities.clear(); + myConstraints.clear(); + + // The workplane will be initialized on first constraint, so its handle is NULL meanwhile + myWorkplane.h = 0; + + // Nullify all elements of the set of equations + myConstrSet.param = 0; + myConstrSet.entity = 0; + myConstrSet.constraint = 0; + myConstrSet.failed = 0; +} + +SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup() +{ + myParams.clear(); + myEntities.clear(); + myConstraints.clear(); + myConstraintMap.clear(); + + if (myConstrSet.param) + delete [] myConstrSet.param; + if (myConstrSet.entity) + delete [] myConstrSet.entity; + if (myConstrSet.constraint) + delete [] myConstrSet.constraint; + if (myConstrSet.failed) + delete [] myConstrSet.failed; +} + +bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isInteract( + boost::shared_ptr theConstraint) const +{ + /// \todo Should be implemented + return false; +} + +bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addConstraint( + boost::shared_ptr theConstraint) +{ + if (myWorkplane.h == 0) + { + // Create workplane when first constraint is added + std::list< boost::shared_ptr > aWPAttr; + theConstraint->getSketchParameters(aWPAttr); + if (!addWorkplane(aWPAttr)) + return false; + } + + // Create constraint parameters + double aDistance = 0.0; // scalar value of the constraint + boost::shared_ptr aDistAttr = + boost::dynamic_pointer_cast(theConstraint->data()->attribute(CONSTRAINT_ATTR_VALUE)); + if (aDistAttr.get()) + aDistance = aDistAttr->value(); + + Slvs_hEntity aPtA, aPtB, aEntityA, aEntityB; // parameters of the constraint + boost::shared_ptr aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_A); + aPtA = addEntity(aEntAttr); + if (aPtA == 0) return false; + aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_B); + aPtB = addEntity(aEntAttr); + if (aPtB == 0) return false; + aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_A); + aEntityA = addEntity(aEntAttr); + if (aEntityA == 0) return false; + aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_B); + aEntityB = addEntity(aEntAttr); + if (aEntityB == 0) return false; + + // Constraint type + int aConstrType = getConstraintType(theConstraint); + if (aConstrType == 0) return false; + + // Create SolveSpace constraint structure + Slvs_Constraint aConstraint = + Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, myWorkplane.h, + aDistance, aPtA, aPtB, aEntityA, aEntityB); + myConstraints.push_back(aConstraint); + myConstraintMap[theConstraint] = *(myConstraints.rbegin()); + + return true; +} + +Slvs_hEntity SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addEntity( + boost::shared_ptr theEntity) +{ + /// \todo Should be implemented + return 0; +} + +bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addWorkplane( + std::list< boost::shared_ptr >& theParams) +{ + /// \todo Should be implemented + return false; +} + +int SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::getConstraintType( + const boost::shared_ptr& theConstraint) const +{ + if (theConstraint->getKind() == SketchPlugin_ConstraintDistance().getKind()) + { + boost::shared_ptr aPtA = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_A); + boost::shared_ptr aPtB = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_B); + boost::shared_ptr aEntA = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_A); + boost::shared_ptr aEntB = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_B); + boost::shared_ptr aDistance = + boost::shared_dynamic_cast(theConstraint->data()->attribute(CONSTRAINT_ATTR_VALUE)); + if (aPtA.get()) // ptA is an attribute of the constraint + { +// if (aEntA.get()) // entityA is an attribute of the constraint +// { +// if (aEntA->feature()->getKind() == SketchPlugin_Line().getKind()) // entityA is a line +// { +// if (aEntB.get() && aEntB->feature()->getKind() == SketchPlugin_Line().getKind()) // entityB is a line too +// return SLVS_C_ANGLE; +// else if (aPtB.get()) // ptB is also an attribute of the constraint +// return SLVS_C_PROJ_PT_DISTANCE; +// else +// return SLVS_C_PT_LINE_DISTANCE; +// } +// /// \todo Implement other point-entity distances +// } +// else + if (aPtB.get()) // ptB is an attribute of the constrtaint => point-point distance + { + if (aDistance->value() == 0.0) + return SLVS_C_POINTS_COINCIDENT; + else + return SLVS_C_PT_PT_DISTANCE; + } + } + else if (aEntA.get() && !aEntB.get() && !aPtB.get()) + return SLVS_C_DIAMETER; + return SLVS_C_UNKNOWN; + } + /// \todo Implement other kind of constrtaints + + return SLVS_C_UNKNOWN; +} diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.h b/src/SketchSolver/SketchSolver_ConstraintManager.h index 376fd2029..7bd108df6 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.h +++ b/src/SketchSolver/SketchSolver_ConstraintManager.h @@ -7,6 +7,22 @@ #include "SketchSolver.h" +#include + +// Need to be defined before including SolveSpace to avoid additional dependances on Windows platform +#if defined(WIN32) && !defined(HAVE_C99_INTEGER_TYPES) +typedef unsigned int UINT32; +#endif +#include +#include + +#include +#include + + +// Unknown constraint (for error reporting) +#define SLVS_C_UNKNOWN 0 + /** \class SketchSolver_ConstraintManager * \ingroup DataModel * \brief Transforms the Constraint feature into the format understandable by SolveSpace library. @@ -17,12 +33,106 @@ */ class SketchSolver_ConstraintManager { +public: + SketchSolver_ConstraintManager(); + ~SketchSolver_ConstraintManager(); + + /** \brief Adds a constraint into the manager + * \param[in] theConstraint constraint to be added + * \return \c true if the constraint added successfully + */ + SKETCHSOLVER_EXPORT bool addConstraint(boost::shared_ptr theConstraint); + + /** \brief Removes a constraint from the manager + * \param[in] theConstraint constraint to be removed + * \return \c true if the constraint removed successfully + */ + SKETCHSOLVER_EXPORT bool removeConstraint(boost::shared_ptr theConstraint); + private: class SketchSolver_ConstraintGroup; + + /** \brief Searches list of groups which interact with specified constraint + * \param[in] theConstraint constraint to be found + * \param[out] theGroups list of group indexes interacted with constraint + */ + void findGroups(boost::shared_ptr theConstraint, + std::vector& theGroupIDs) const; + +private: + std::vector myGroups; ///< groups of constraints }; + +/** \class SketchSolver_ConstraintGroup + * \ingroup DataModel + * \brief Keeps the group of constraints which based on the same entities + */ class SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup { +public: + SketchSolver_ConstraintGroup(); + ~SketchSolver_ConstraintGroup(); + + /// \brief Returns group's unique identifier + const Slvs_hGroup& getId() const + {return myID;} + + /** \brief Adds a constraint into the group + * \param[in] theConstraint constraint to be added + * \return \c true if the constraint added successfully + */ + bool addConstraint(boost::shared_ptr theConstraint); + + /** \brief Removes a constraint into the group + * \param[in] theConstraint constraint to be removed + * \return \c true if the constraint removed successfully + */ + bool removeConstraint(boost::shared_ptr theConstraint); + + /** \brief Verifies the constraint uses the objects from this group + * \param[in] theConstraint constraint for verification of interaction + * \return \c true if the constrained objects are used in current group + */ + bool isInteract(boost::shared_ptr theConstraint) const; + +protected: + /** \brief Creates a workplane from the sketch parameters + * \param[in] theParams list of the basic parameters of the workplane + * \return \c true if success + */ + bool addWorkplane(std::list< boost::shared_ptr >& theParams); + + /** \brief Adds an entity into the group + * \param[in] theEntity the object of constraint + * \return identifier of created entity or 0 if entity was not added + */ + Slvs_hEntity addEntity(boost::shared_ptr theEntity); + + /** \brief Adds a parameter into the group + * \param[in] theParam parameter to be added + * \return identifier of created parameter or 0 if it was not added + */ + Slvs_hParam addParameter(double theParam); + + /** \brief Compute constraint type according to SolveSpace identifiers + * \param[in] theConstraint constraint which type should be determined + * \return identifier of constraint type + */ + int getConstraintType(const boost::shared_ptr& theConstraint) const; + +private: + Slvs_hGroup myID; ///< the index of the group + Slvs_Entity myWorkplane; ///< Workplane for the current group + std::vector myParams; ///< List of parameters of the constraints + Slvs_hParam myParamMaxID; ///< Actual maximal ID of parameters + std::vector myEntities; ///< List of entities of the constaints + Slvs_hEntity myEntityMaxID; ///< Actual maximal ID of entities + std::vector myConstraints; ///< List of constraints in SolveSpace format + Slvs_hConstraint myConstrMaxID; ///< Actual maximal ID of constraints + Slvs_System myConstrSet; ///< SolveSpace's set of equations obtained by constraints + std::map, Slvs_Constraint> + myConstraintMap; ///< The map between SketchPlugin and SolveSpace constraints }; #endif -- 2.39.2