From fe55d1385d83a74a7bfd0d1a5bd18d408009e6ab Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 14 May 2014 11:59:12 +0400 Subject: [PATCH] Implemented methods for adding constraints --- src/SketchPlugin/SketchPlugin_Constraint.h | 3 +- .../SketchSolver_ConstraintManager.cpp | 182 +++++++++++------- .../SketchSolver_ConstraintManager.h | 13 +- 3 files changed, 129 insertions(+), 69 deletions(-) diff --git a/src/SketchPlugin/SketchPlugin_Constraint.h b/src/SketchPlugin/SketchPlugin_Constraint.h index e69a316cc..61cd2bf05 100644 --- a/src/SketchPlugin/SketchPlugin_Constraint.h +++ b/src/SketchPlugin/SketchPlugin_Constraint.h @@ -34,7 +34,8 @@ const std::string CONSTRAINT_ATTR_ENTITY_C("ConstraintEntityC"); /// Fourth entity for the constraint const std::string CONSTRAINT_ATTR_ENTITY_D("ConstraintEntityD"); /// List of constraint attributes -const std::string CONSTRAINT_ATTRIBUTES[4] = +const unsigned int CONSTRAINT_ATTR_SIZE = 4; +const std::string CONSTRAINT_ATTRIBUTES[CONSTRAINT_ATTR_SIZE] = {CONSTRAINT_ATTR_ENTITY_A, CONSTRAINT_ATTR_ENTITY_B, CONSTRAINT_ATTR_ENTITY_C, CONSTRAINT_ATTR_ENTITY_D}; diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index a95f3c17f..777519914 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -84,7 +85,7 @@ void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessa boost::dynamic_pointer_cast(aUpdateMsg->feature()); if (aSketch) { - updateWorkplane(aSketch); +// updateWorkplane(aSketch); return ; } @@ -92,14 +93,14 @@ void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessa boost::dynamic_pointer_cast(aUpdateMsg->feature()); if (aConstraint) { - updateConstraint(aConstraint); +// updateConstraint(aConstraint); return ; } boost::shared_ptr aFeature = boost::dynamic_pointer_cast(aUpdateMsg->feature()); - if (aFeature) - updateEntity(aFeature); +// if (aFeature) +// updateEntity(aFeature); } } @@ -120,6 +121,37 @@ bool SketchSolver_ConstraintManager::addWorkplane(boost::shared_ptr theConstraint) +{ + // Search the groups which this constraint touchs + std::vector aGroups; + findGroups(theConstraint, aGroups); + + // Process the groups list + if (aGroups.size() == 0) + { // There are no groups applicable for this constraint => create new one + SketchSolver_ConstraintGroup aGroup(findWorkplaneForConstraint(theConstraint)); + aGroup.addConstraint(theConstraint); + myGroups.push_back(aGroup); + } + else if (aGroups.size() == 1) + { // Only one group => add constraint into it + Slvs_hGroup aGroupId = *(aGroups.begin()); + std::vector::iterator aGroupIter; + for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) + if (aGroupIter->getId() == aGroupId) + return aGroupIter->addConstraint(theConstraint); + } + else if (aGroups.size() > 1) + { // Several groups applicable for this constraint => need to merge them + /// \todo Implement merging of groups + } + + // Something goes wrong + return false; +} + void SketchSolver_ConstraintManager::findGroups( boost::shared_ptr theConstraint, @@ -131,6 +163,26 @@ void SketchSolver_ConstraintManager::findGroups( theGroupIDs.push_back(aGroupIter->getId()); } +boost::shared_ptr SketchSolver_ConstraintManager::findWorkplaneForConstraint( + boost::shared_ptr theConstraint) const +{ + std::vector::const_iterator aGroupIter; + for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) + { + boost::shared_ptr aWP = aGroupIter->getWorkplane(); + boost::shared_ptr aWPFeatures = + boost::dynamic_pointer_cast(aWP->data()->attribute(SKETCH_ATTR_FEATURES)); + std::list< boost::shared_ptr > aFeaturesList = aWPFeatures->list(); + std::list< boost::shared_ptr >::const_iterator anIter; + for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++) + if (*anIter == theConstraint) + return aWP; // workplane is found + } + + return boost::shared_ptr(); +} + + // ======================================================== // ========= SketchSolver_ConstraintGroup =============== @@ -192,45 +244,36 @@ bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isInteract( bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addConstraint( boost::shared_ptr theConstraint) { + // There is no workplane yet, something wrong 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; - } + return false; + + // Get constraint type and verify the constraint parameters are correct + int aConstrType = getConstraintType(theConstraint); + if (aConstrType == SLVS_C_UNKNOWN) + 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()) + if (aDistAttr) aDistance = aDistAttr->value(); - /// \todo Specify the entities - Slvs_hEntity aPtA, aPtB, aEntityA, aEntityB; // parameters of the constraint - boost::shared_ptr aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_A); - aPtA = addEntity(aEntAttr); - if (aPtA == 0) return false; - aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_B); - aPtB = addEntity(aEntAttr); - if (aPtB == 0) return false; - aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_C); - aEntityA = addEntity(aEntAttr); - if (aEntityA == 0) return false; - aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_D); - aEntityB = addEntity(aEntAttr); - if (aEntityB == 0) return false; - - // Constraint type - int aConstrType = getConstraintType(theConstraint); - if (aConstrType == 0) return false; + Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint + for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) + { + boost::shared_ptr aConstrAttr = + boost::dynamic_pointer_cast( + theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) + ); + aConstrEnt[indAttr] = addEntity(aConstrAttr->attr()); + } // Create SolveSpace constraint structure Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, myWorkplane.h, - aDistance, aPtA, aPtB, aEntityA, aEntityB); + aDistance, aConstrEnt[0], aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]); myConstraints.push_back(aConstraint); myConstraintMap[theConstraint] = *(myConstraints.rbegin()); @@ -332,42 +375,47 @@ Slvs_hParam SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addPar 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; -// } + // Constraint for coincidence of two points + boost::shared_ptr aPtEquiv = + boost::dynamic_pointer_cast(theConstraint); + if (aPtEquiv) + { + // 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]) + ); + // Verify the attribute is a 2D point + boost::shared_ptr aPoint2D = + boost::dynamic_pointer_cast(anAttr->attr()); + if (aPoint2D) + { + aPt2d |= (1 << indAttr); + continue; + } + // Verify the attribute is a 3D point + boost::shared_ptr aPoint3D = + boost::dynamic_pointer_cast(anAttr->attr()); + if (aPoint3D) + { + aPt3d |= (1 << 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; + } + /// \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 80843c6b8..d80b9d9dc 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.h +++ b/src/SketchSolver/SketchSolver_ConstraintManager.h @@ -105,6 +105,13 @@ private: void findGroups(boost::shared_ptr theConstraint, std::vector& theGroupIDs) const; + /** \brief Searches in the list of groups the workplane which constains specified constraint + * \param[in] theConstraint constraint to be found + * \return workplane contains the constraint + */ + boost::shared_ptr findWorkplaneForConstraint( + boost::shared_ptr theConstraint) const; + private: static SketchSolver_ConstraintManager* _self; ///< Self pointer to implement singleton functionality std::vector myGroups; ///< Groups of constraints @@ -152,6 +159,9 @@ public: */ bool isBaseWorkplane(boost::shared_ptr theWorkplane) const; + boost::shared_ptr getWorkplane() const + { return mySketch; } + protected: /** \brief Adds an entity into the group * @@ -185,8 +195,9 @@ protected: Slvs_hParam addParameter(double theParam); /** \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 + * \return identifier of constraint type or SLVS_C_UNKNOWN if the type is wrong */ int getConstraintType(const boost::shared_ptr& theConstraint) const; -- 2.39.2