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
)
--- /dev/null
+// File: SketchSolver_Constraint.cpp
+// Created: 27 May 2014
+// Author: Artem ZHIDKOV
+
+#include "SketchSolver_Constraint.h"
+#include <SketchSolver_Solver.h>
+
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_Data.h>
+
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
+
+
+SketchSolver_Constraint::SketchSolver_Constraint()
+ : myConstraint(boost::shared_ptr<SketchPlugin_Constraint>()),
+ myType(SLVS_C_UNKNOWN),
+ myAttributesList()
+{
+}
+
+SketchSolver_Constraint::SketchSolver_Constraint(
+ boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
+ : myConstraint(theConstraint),
+ myAttributesList()
+{
+ myType = getType(myConstraint);
+}
+
+const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Constraint> 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<ModelAPI_AttributeRefAttr> anAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
+ );
+ if (!anAttr) continue;
+ // 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);
+ myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[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);
+ 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<ModelAPI_AttributeRefAttr> anAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ 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<GeomDataAPI_Point2D> aPoint2D =
+ boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
+ if (aPoint2D)
+ {
+ myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[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)
+ {
+ 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<ModelAPI_AttributeRefAttr> anAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ 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<ModelAPI_AttributeRefAttr> anAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ 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();
+}
--- /dev/null
+// File: SketchSolver_Constraint.h
+// Created: 27 May 2014
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_Constraint_Headerfile
+#define SketchSolver_Constraint_Headerfile
+
+#include "SketchSolver.h"
+
+#include <SketchPlugin_Constraint.h>
+
+#include <string>
+#include <vector>
+
+/** \class SketchSolver_Constraint
+ * \ingroup DataModel
+ * \brief Obtain information about SketchPlugin's constraint
+ */
+class SketchSolver_Constraint
+{
+public:
+ SketchSolver_Constraint();
+ SketchSolver_Constraint(boost::shared_ptr<SketchPlugin_Constraint> 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<SketchPlugin_Constraint> 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<std::string>& getAttributes() const
+ { return myAttributesList; }
+
+private:
+ boost::shared_ptr<SketchPlugin_Constraint> myConstraint;
+ int myType;
+ std::vector<std::string> myAttributesList;
+};
+
+#endif
#include "SketchSolver_ConstraintManager.h"
+#include <SketchSolver_Constraint.h>
+
#include <Events_Loop.h>
#include <GeomDataAPI_Dir.h>
#include <GeomDataAPI_Point.h>
}
// Get constraint type and verify the constraint parameters are correct
- std::vector<std::string> 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<std::string>& aConstraintAttributes = aConstraint.getAttributes();
// Create constraint parameters
double aDistance = 0.0; // scalar value of the constraint
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<SketchPlugin_Constraint>& theConstraint,
- std::vector<std::string>& 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<ModelAPI_AttributeRefAttr> anAttr =
- boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
- );
- if (!anAttr) continue;
- // 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);
- theAttrNames[anAttrPos++] = CONSTRAINT_ATTRIBUTES[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);
- 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<ModelAPI_AttributeRefAttr> anAttr =
- boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- 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<GeomDataAPI_Point2D> aPoint2D =
- boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
- if (aPoint2D)
- {
- theAttrNames[aNbPoints++] = CONSTRAINT_ATTRIBUTES[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)
- {
- 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<ModelAPI_AttributeRefAttr> anAttr =
- boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- 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<ModelAPI_AttributeRefAttr> anAttr =
- boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- 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
#include <set>
-// 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
Slvs_hParam changeParameter(const double& theParam,
std::vector<Slvs_Param>::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<SketchPlugin_Constraint>& theConstraint,
- std::vector<std::string>& 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
#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
{