#include "SketchSolver_ConstraintManager.h"
+#include <Events_Loop.h>
+#include <GeomDataAPI_Dir.h>
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_Data.h>
+#include <Model_Events.h>
#include <SketchPlugin_Constraint.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Sketch.h>
+SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0;
+
+/// Global constaint manager object
+SketchSolver_ConstraintManager* myManager = SketchSolver_ConstraintManager::Instance();
/// This value is used to give unique index to the groups
static Slvs_hGroup myGroupIndexer = 0;
// ========================================================
// ========= SketchSolver_ConstraintManager ===============
// ========================================================
+SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::Instance()
+{
+ if (!_self)
+ _self = new SketchSolver_ConstraintManager();
+ return _self;
+}
+
SketchSolver_ConstraintManager::SketchSolver_ConstraintManager()
{
myGroups.clear();
+
+ // Register in event loop
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
}
SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager()
myGroups.clear();
}
+void SketchSolver_ConstraintManager::processEvent(const Events_Message* theMessage)
+{
+ if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED))
+ {
+ const Model_FeatureUpdatedMessage* aCreateMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+
+ // Only sketches and constraints can be added by Create event
+ boost::shared_ptr<SketchPlugin_Sketch> aSketch =
+ boost::dynamic_pointer_cast<SketchPlugin_Sketch>(aCreateMsg->feature());
+ if (aSketch)
+ {
+ addWorkplane(aSketch);
+ return ;
+ }
+ boost::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ boost::dynamic_pointer_cast<SketchPlugin_Constraint>(aCreateMsg->feature());
+ if (aConstraint)
+ {
+ addConstraint(aConstraint);
+ return ;
+ }
+ }
+ else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_DELETED))
+ {
+ const Model_FeatureDeletedMessage* aDeleteMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
+ /// \todo Implement deleting objects on event
+ }
+ else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED))
+ {
+ const Model_FeatureUpdatedMessage* aUpdateMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+
+ boost::shared_ptr<SketchPlugin_Sketch> aSketch =
+ boost::dynamic_pointer_cast<SketchPlugin_Sketch>(aUpdateMsg->feature());
+ if (aSketch)
+ {
+// updateWorkplane(aSketch);
+ return ;
+ }
+
+ boost::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ boost::dynamic_pointer_cast<SketchPlugin_Constraint>(aUpdateMsg->feature());
+ if (aConstraint)
+ {
+// updateConstraint(aConstraint);
+ return ;
+ }
+
+ boost::shared_ptr<SketchPlugin_Feature> aFeature =
+ boost::dynamic_pointer_cast<SketchPlugin_Feature>(aUpdateMsg->feature());
+// if (aFeature)
+// updateEntity(aFeature);
+ }
+}
+
+
+bool SketchSolver_ConstraintManager::addWorkplane(boost::shared_ptr<SketchPlugin_Sketch> theSketch)
+{
+ // Check the specified workplane is already used
+ std::vector<SketchSolver_ConstraintGroup>::const_iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+ if (aGroupIter->isBaseWorkplane(theSketch))
+ return true;
+ // Create new group for workplane
+ SketchSolver_ConstraintGroup aNewGroup(theSketch);
+ // Verify that the group is created successfully
+ if (!aNewGroup.isBaseWorkplane(theSketch))
+ return false;
+ myGroups.push_back(aNewGroup);
+ return true;
+}
+
+bool SketchSolver_ConstraintManager::addConstraint(
+ boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
+{
+ // Search the groups which this constraint touchs
+ std::vector<Slvs_hGroup> 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<SketchSolver_ConstraintGroup>::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<SketchPlugin_Constraint> theConstraint,
std::vector<Slvs_hGroup>& theGroupIDs) const
theGroupIDs.push_back(aGroupIter->getId());
}
+boost::shared_ptr<SketchPlugin_Sketch> SketchSolver_ConstraintManager::findWorkplaneForConstraint(
+ boost::shared_ptr<SketchPlugin_Constraint> theConstraint) const
+{
+ std::vector<SketchSolver_ConstraintGroup>::const_iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+ {
+ boost::shared_ptr<SketchPlugin_Sketch> aWP = aGroupIter->getWorkplane();
+ boost::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aWP->data()->attribute(SKETCH_ATTR_FEATURES));
+ std::list< boost::shared_ptr<ModelAPI_Feature> > aFeaturesList = aWPFeatures->list();
+ std::list< boost::shared_ptr<ModelAPI_Feature> >::const_iterator anIter;
+ for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
+ if (*anIter == theConstraint)
+ return aWP; // workplane is found
+ }
+
+ return boost::shared_ptr<SketchPlugin_Sketch>();
+}
+
+
// ========================================================
// ========= SketchSolver_ConstraintGroup ===============
// ========================================================
-SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::SketchSolver_ConstraintGroup()
+SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::
+ SketchSolver_ConstraintGroup(boost::shared_ptr<SketchPlugin_Sketch> theWorkplane)
: myID(++myGroupIndexer),
myParamMaxID(0),
myEntityMaxID(0),
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;
+
+ // Initialize workplane
+ myWorkplane.h = 0;
+ addWorkplane(theWorkplane);
}
SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup()
delete [] myConstrSet.failed;
}
+bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isBaseWorkplane(
+ boost::shared_ptr<SketchPlugin_Sketch> theWorkplane) const
+{
+ return theWorkplane == mySketch;
+}
+
bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isInteract(
boost::shared_ptr<SketchPlugin_Constraint> theConstraint) const
{
bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addConstraint(
boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
{
+ // There is no workplane yet, something wrong
if (myWorkplane.h == 0)
- {
-// // Create workplane when first constraint is added
-// std::list< boost::shared_ptr<ModelAPI_Attribute> > 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<ModelAPI_AttributeDouble> aDistAttr =
boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(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<ModelAPI_Attribute> 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<ModelAPI_AttributeRefAttr> aConstrAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ 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());
Slvs_hEntity SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addEntity(
boost::shared_ptr<ModelAPI_Attribute> theEntity)
{
- /// \todo Should be implemented
+ // Look over supported types of entities
+
+ // Point in 3D
+ boost::shared_ptr<GeomDataAPI_Point> aPoint =
+ boost::dynamic_pointer_cast<GeomDataAPI_Point>(theEntity);
+ if (aPoint)
+ {
+ Slvs_hParam aX = addParameter(aPoint->x());
+ Slvs_hParam aY = addParameter(aPoint->y());
+ Slvs_hParam aZ = addParameter(aPoint->z());
+ Slvs_Entity aPtEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ);
+ myEntities.push_back(aPtEntity);
+ return aPtEntity.h;
+ }
+
+ // Point in 2D
+ boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
+ if (aPoint2D)
+ {
+ // The 2D points are created on workplane. So, if there is no workplane yet, then error
+ if (myWorkplane.h == 0)
+ return 0;
+ Slvs_hParam aU = addParameter(aPoint2D->x());
+ Slvs_hParam aV = addParameter(aPoint2D->y());
+ Slvs_Entity aPt2DEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV);
+ myEntities.push_back(aPt2DEntity);
+ return aPt2DEntity.h;
+ }
+
+ /// \todo Other types of entities
+
+ // Unsupported or wrong entity type
return 0;
}
+Slvs_hEntity SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addNormal(
+ boost::shared_ptr<ModelAPI_Attribute> theDirX,
+ boost::shared_ptr<ModelAPI_Attribute> theDirY)
+{
+ boost::shared_ptr<GeomDataAPI_Dir> aDirX = boost::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
+ boost::shared_ptr<GeomDataAPI_Dir> aDirY = boost::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirY);
+ if (!aDirX || !aDirY)
+ return 0;
+
+ // quaternion parameters of normal vector
+ double qw, qx, qy, qz;
+ Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(),
+ aDirY->x(), aDirY->y(), aDirY->z(),
+ &qw, &qx, &qy, &qz);
+
+ // Create a normal
+ Slvs_Entity aNormal = Slvs_MakeNormal3d(++myEntityMaxID, myID,
+ addParameter(qw), addParameter(qx), addParameter(qy), addParameter(qz));
+ myEntities.push_back(aNormal);
+ return aNormal.h;
+}
+
+
bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addWorkplane(
- std::list< boost::shared_ptr<ModelAPI_Attribute> >& theParams)
+ boost::shared_ptr<SketchPlugin_Sketch> theSketch)
{
- /// \todo Should be implemented
- return false;
+ if (myWorkplane.h)
+ return false; // the workplane already exists
+
+ // Get parameters of workplane
+ boost::shared_ptr<ModelAPI_Attribute> aDirX = theSketch->data()->attribute(SKETCH_ATTR_DIRX);
+ boost::shared_ptr<ModelAPI_Attribute> aDirY = theSketch->data()->attribute(SKETCH_ATTR_DIRY);
+ boost::shared_ptr<ModelAPI_Attribute> anOrigin = theSketch->data()->attribute(SKETCH_ATTR_ORIGIN);
+ // Transform them into SolveSpace format
+ Slvs_hEntity aNormalWP = addNormal(aDirX, aDirY);
+ if (!aNormalWP) return false;
+ Slvs_hEntity anOriginWP = addEntity(anOrigin);
+ if (!anOriginWP) return false;
+ // Create workplane
+ myWorkplane = Slvs_MakeWorkplane(++myEntityMaxID, myID, anOriginWP, aNormalWP);
+ mySketch = theSketch;
+ // Workplane should be added to the list of entities
+ myEntities.push_back(myWorkplane);
+ return true;
+}
+
+Slvs_hParam SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addParameter(double theParam)
+{
+ Slvs_Param aParam = Slvs_MakeParam(++myParamMaxID, myID, theParam);
+ myParams.push_back(aParam);
+ return aParam.h;
}
int SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::getConstraintType(
const boost::shared_ptr<SketchPlugin_Constraint>& theConstraint) const
{
-// if (theConstraint->getKind() == SketchPlugin_ConstraintDistance().getKind())
-// {
-// boost::shared_ptr<ModelAPI_Attribute> aPtA = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_A);
-// boost::shared_ptr<ModelAPI_Attribute> aPtB = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_B);
-// boost::shared_ptr<ModelAPI_Attribute> aEntA = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_A);
-// boost::shared_ptr<ModelAPI_Attribute> aEntB = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_B);
-// boost::shared_ptr<ModelAPI_AttributeDouble> aDistance =
-// boost::shared_dynamic_cast<ModelAPI_AttributeDouble>(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<SketchPlugin_ConstraintCoincidence> aPtEquiv =
+ boost::dynamic_pointer_cast<SketchPlugin_ConstraintCoincidence>(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<ModelAPI_AttributeRefAttr> anAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
+ );
+ // Verify the attribute is a 2D point
+ boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
+ if (aPoint2D)
+ {
+ aPt2d |= (1 << indAttr);
+ continue;
+ }
+ // Verify the attribute is a 3D point
+ boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
+ boost::dynamic_pointer_cast<GeomDataAPI_Point>(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;
#include "SketchSolver.h"
+#include <Events_Listener.h>
#include <SketchPlugin_Constraint.h>
// Need to be defined before including SolveSpace to avoid additional dependances on Windows platform
/** \class SketchSolver_ConstraintManager
* \ingroup DataModel
- * \brief Transforms the Constraint feature into the format understandable by SolveSpace library.
+ * \brief Listens the changes of SketchPlugin features and transforms the Constraint
+ * feature into the format understandable by SolveSpace library.
*
- * Constraints created for SolveSpace library will be divided into the groups.
+ * Constraints created for SolveSpace library are divided into the groups.
* The division order based on connectedness of the features by the constraints.
* The groups may be fused or separated according to the new constraints.
+ *
+ * \remark This is a singleton.
*/
-class SketchSolver_ConstraintManager
+class SketchSolver_ConstraintManager : public Events_Listener
{
public:
+ /** \brief Main method to create constraint manager
+ * \return pointer to the singleton
+ */
+ static SketchSolver_ConstraintManager* Instance();
+
+ /** \brief Implementation of Event Listener method
+ * \param[in] theMessage the data of the event
+ */
+ virtual void processEvent(const Events_Message* theMessage);
+
+protected:
SketchSolver_ConstraintManager();
~SketchSolver_ConstraintManager();
* \param[in] theConstraint constraint to be added
* \return \c true if the constraint added successfully
*/
- SKETCHSOLVER_EXPORT bool addConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+ bool addConstraint(boost::shared_ptr<SketchPlugin_Constraint> 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<SketchPlugin_Constraint> theConstraint);
+ bool removeConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+ /** \brief Updates a constraint
+ * \param[in] theConstraint constraint to be updated
+ * \return \c true if the constraint was updated
+ */
+ bool updateConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+ /** \brief Adds a workplane into the manager
+ * \param[in] theSketch the feature to create workplane
+ * \return \c true if the workplane added successfully
+ */
+ bool addWorkplane(boost::shared_ptr<SketchPlugin_Sketch> theSketch);
+
+ /** \brief Removes a workplane from the manager.
+ * All groups based on such workplane will be removed too.
+ * \param[in] theSketch the feature to be removed
+ * \return \c true if the workplane removed successfully
+ */
+ bool removeWorkplane(boost::shared_ptr<SketchPlugin_Sketch> theSketch);
+
+ /** \brief Updates a workplane
+ * \param[in] theSketch workplane to be updated
+ * \return \c true if the workplane was updated
+ */
+ bool updateWorkplane(boost::shared_ptr<SketchPlugin_Sketch> theSketch);
+
+ /** \brief Updates entity which is neither workplane nor constraint
+ * \param[in] theFeature entity to be updated
+ * \return \c true if the entity updated successfully
+ */
+ bool updateEntity(boost::shared_ptr<SketchPlugin_Feature> theFeature);
private:
class SketchSolver_ConstraintGroup;
void findGroups(boost::shared_ptr<SketchPlugin_Constraint> theConstraint,
std::vector<Slvs_hGroup>& 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<SketchPlugin_Sketch> findWorkplaneForConstraint(
+ boost::shared_ptr<SketchPlugin_Constraint> theConstraint) const;
+
private:
- std::vector<SketchSolver_ConstraintGroup> myGroups; ///< groups of constraints
+ static SketchSolver_ConstraintManager* _self; ///< Self pointer to implement singleton functionality
+ std::vector<SketchSolver_ConstraintGroup> myGroups; ///< Groups of constraints
};
class SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup
{
public:
- SketchSolver_ConstraintGroup();
+ /** \brief New group based on specified workplane
+ */
+ SketchSolver_ConstraintGroup(boost::shared_ptr<SketchPlugin_Sketch> theWorkplane);
+
~SketchSolver_ConstraintGroup();
/// \brief Returns group's unique identifier
*/
bool isInteract(boost::shared_ptr<SketchPlugin_Constraint> 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
+ /** \brief Verifies the specified workplane is the same as a base workplane for this group
+ * \param[in] theWorkplane workplane to be compared
+ * \return \c true if workplanes are the same
*/
- bool addWorkplane(std::list< boost::shared_ptr<ModelAPI_Attribute> >& theParams);
+ bool isBaseWorkplane(boost::shared_ptr<SketchPlugin_Sketch> theWorkplane) const;
+ boost::shared_ptr<SketchPlugin_Sketch> getWorkplane() const
+ { return mySketch; }
+
+protected:
/** \brief Adds an entity into the group
+ *
+ * The parameters of entity will be parsed and added to the list of SolveSpace parameters.
+ * Parameters of certain entity will be placed sequentially in the list.
+ *
* \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<ModelAPI_Attribute> theEntity);
+ /** \brief Adds a normal into the group
+ *
+ * Normal is a special entity in SolveSpace, which defines a direction in 3D and
+ * a rotation about this direction. So, SolveSpace represents normals as unit quaternions.
+ *
+ * To define a normal there should be specified two coordinate axis
+ * on the plane transversed to created normal.
+ *
+ * \param[in] theDirX first coordinate axis of the plane
+ * \param[in] theDirY second coordinate axis of the plane
+ * \return identifier of created normal
+ */
+ Slvs_hEntity addNormal(boost::shared_ptr<ModelAPI_Attribute> theDirX,
+ boost::shared_ptr<ModelAPI_Attribute> theDirY);
+
/** \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
+ * 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<SketchPlugin_Constraint>& theConstraint) const;
private:
+ /** \brief Creates a workplane from the sketch parameters
+ * \param[in] theSketch parameters of workplane are the attributes of this sketch
+ * \return \c true if success
+ */
+ bool addWorkplane(boost::shared_ptr<SketchPlugin_Sketch> theSketch);
+
+private:
+ // SolveSpace entities
Slvs_hGroup myID; ///< the index of the group
Slvs_Entity myWorkplane; ///< Workplane for the current group
std::vector<Slvs_Param> myParams; ///< List of parameters of the constraints
- Slvs_hParam myParamMaxID; ///< Actual maximal ID of parameters
+ Slvs_hParam myParamMaxID; ///< Actual maximal ID of parameters (not equal to myParams size)
std::vector<Slvs_Entity> myEntities; ///< List of entities of the constaints
- Slvs_hEntity myEntityMaxID; ///< Actual maximal ID of entities
+ Slvs_hEntity myEntityMaxID; ///< Actual maximal ID of entities (not equal to myEntities size)
std::vector<Slvs_Constraint> myConstraints; ///< List of constraints in SolveSpace format
- Slvs_hConstraint myConstrMaxID; ///< Actual maximal ID of constraints
+ Slvs_hConstraint myConstrMaxID; ///< Actual maximal ID of constraints (not equal to myConstraints size)
Slvs_System myConstrSet; ///< SolveSpace's set of equations obtained by constraints
+
+ // SketchPlugin entities
+ boost::shared_ptr<SketchPlugin_Sketch> mySketch; ///< Equivalent to workplane
std::map<boost::shared_ptr<SketchPlugin_Constraint>, Slvs_Constraint>
myConstraintMap; ///< The map between SketchPlugin and SolveSpace constraints
};