+// ============================================================================
+// Function: changeRigidConstraint
+// Class: SketchSolver_ConstraintGroup
+// Purpose: create/update the "Rigid" constraint in the group
+// ============================================================================
+bool SketchSolver_ConstraintGroup::changeRigidConstraint(
+ std::shared_ptr<SketchPlugin_Constraint> theConstraint)
+{
+ // Search this constraint in the current group to update it
+ ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
+ std::vector<Slvs_Constraint>::iterator aConstrIter;
+ if (aConstrMapIter != myConstraintMap.end()) {
+ int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
+ aConstrIter = myConstraints.begin() + aConstrPos;
+ }
+
+ // Get constraint type and verify the constraint parameters are correct
+ 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();
+
+ Slvs_hEntity aConstrEnt = SLVS_E_UNKNOWN;
+ std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
+ ModelAPI_AttributeRefAttr>(
+ theConstraint->data()->attribute(aConstraintAttributes[0]));
+ if (!aConstrAttr)
+ return false;
+
+ // Convert the object of the attribute to the feature
+ FeaturePtr aFeature;
+ if (aConstrAttr->isObject() && aConstrAttr->object()) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ aConstrAttr->object());
+ if (!aRC)
+ return false;
+ std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
+ aFeature = aDoc->feature(aRC);
+ }
+
+ aConstrEnt = aConstrAttr->isObject() ? changeEntityFeature(aFeature) : changeEntity(aConstrAttr->attr());
+
+ if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
+ // Check the fixed entity is not a point.
+ std::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr = std::dynamic_pointer_cast<
+ ModelAPI_AttributeRefAttr>(theConstraint->data()->attribute(aConstraintAttributes[0]));
+ std::shared_ptr<GeomDataAPI_Point> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point>(aConstrAttr->attr());
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aConstrAttr->attr());
+ if (aPoint || aPoint2D) {
+ // Create SolveSpace constraint structure
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
+ aConstrEnt, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aConstraint.h);
+ int aConstrPos = Search(aConstraint.h, myConstraints);
+ aConstrIter = myConstraints.begin() + aConstrPos;
+ myNeedToSolve = true;
+ } else {
+ myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>();
+
+ // To avoid SolveSpace problems:
+ // * if the circle is rigid, we will fix its center and radius;
+ // * if the arc is rigid, we will fix its start and end points and radius.
+ double aRadius = 0.0;
+ bool isArc = false;
+ bool isCircle = false;
+ if (aFeature) {
+ if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
+ std::shared_ptr<GeomDataAPI_Point2D> aCenter =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStart =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->data()->attribute(SketchPlugin_Arc::START_ID()));
+ aRadius = aStart->pnt()->distance(aCenter->pnt());
+ isArc = true;
+ } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
+ aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()))->value();
+ isCircle = true;
+ }
+ }
+
+ // Get list of already fixed points
+ std::set<Slvs_hEntity> anAlreadyFixed;
+ std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); aCIter++)
+ if (aCIter->type == SLVS_C_WHERE_DRAGGED)
+ anAlreadyFixed.insert(aCIter->ptA);
+
+ // Create constraints to fix the parameters of the entity
+ int aEntPos = Search(aConstrEnt, myEntities);
+ Slvs_hEntity* aPointsPtr = myEntities[aEntPos].point;
+ if (isArc) aPointsPtr++; // avoid to fix center of arc
+ while (*aPointsPtr != 0) {
+ // Avoid to create additional "Rigid" constraints for coincident points
+ bool isCoincAlreadyFixed = false;
+ if (!anAlreadyFixed.empty()) {
+ if (anAlreadyFixed.find(*aPointsPtr) != anAlreadyFixed.end())
+ isCoincAlreadyFixed = true;
+
+ std::vector<std::set<Slvs_hEntity> >::const_iterator aCoincIter =
+ myCoincidentPoints.begin();
+ for (; !isCoincAlreadyFixed && aCoincIter != myCoincidentPoints.end(); aCoincIter++) {
+ if (aCoincIter->find(*aPointsPtr) == aCoincIter->end())
+ continue;
+ std::set<Slvs_hEntity>::const_iterator anIter = anAlreadyFixed.begin();
+ for (; !isCoincAlreadyFixed && anIter != anAlreadyFixed.end(); anIter++)
+ if (aCoincIter->find(*anIter) != aCoincIter->end())
+ isCoincAlreadyFixed = true;
+ }
+ }
+
+ if (!isCoincAlreadyFixed) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
+ *aPointsPtr, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint].push_back(aConstraint.h);
+ }
+ aPointsPtr++;
+ }
+
+ if (isArc || isCircle) { // add radius constraint
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, 2.0 * aRadius,
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aConstrEnt, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint].push_back(aConstraint.h);
+ }
+
+ // The object is already rigid, so there is no constraints added
+ if (myConstraintMap[theConstraint].empty()) {
+ myConstraintMap.erase(theConstraint);
+ myNeedToSolve = false;
+ }
+ else
+ myNeedToSolve = true;
+ }
+ }
+ return true;
+}
+