- return boost::shared_ptr<SketchPlugin_Feature>();
-}
-
-void SketchSolver_ConstraintManager::resolveConstraints()
-{
- std::vector<SketchSolver_ConstraintGroup*>::iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- (*aGroupIter)->resolveConstraints();
-
- // Features may be updated => send events
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
-}
-
-
-
-// ========================================================
-// ========= SketchSolver_ConstraintGroup ===============
-// ========================================================
-
-SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::
- SketchSolver_ConstraintGroup(boost::shared_ptr<SketchPlugin_Feature> theWorkplane)
- : myID(++myGroupIndexer),
- myParamMaxID(0),
- myEntityMaxID(0),
- myConstrMaxID(0),
- myConstraintMap(),
- myNeedToSolve(false),
- myConstrSolver()
-{
- myParams.clear();
- myEntities.clear();
- myConstraints.clear();
-
- // Initialize workplane
- myWorkplane.h = SLVS_E_UNKNOWN;
-#ifndef NDEBUG
- assert(addWorkplane(theWorkplane));
-#else
- addWorkplane(theWorkplane);
-#endif
-}
-
-SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup()
-{
- myParams.clear();
- myEntities.clear();
- myConstraints.clear();
- myConstraintMap.clear();
-
- // If the group with maximal identifier is deleted, decrease the indexer
- if (myID == myGroupIndexer)
- myGroupIndexer--;
-}
-
-bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isBaseWorkplane(
- boost::shared_ptr<SketchPlugin_Feature> theWorkplane) const
-{
- return theWorkplane == mySketch;
-}
-
-bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isInteract(
- boost::shared_ptr<SketchPlugin_Constraint> theConstraint) const
-{
- // Check the group is empty
- if (myWorkplane.h != SLVS_E_UNKNOWN && myConstraints.empty())
- return true;
-
- // Go through constraint entities and verify if some of them already in the group
- for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
- {
- boost::shared_ptr<ModelAPI_AttributeRefAttr> aCAttrRef =
- boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[i])
- );
- if (!aCAttrRef) continue;
- if (myEntityMap.find(aCAttrRef->attr()) != myEntityMap.end())
- return true;
- }
-
- // Entities did not found
- return false;
-}
-
-bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::changeConstraint(
- boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
-{
- // There is no workplane yet, something wrong
- if (myWorkplane.h == SLVS_E_UNKNOWN)
- return false;
-
- // Search this constraint in the current group to update it
- std::map<boost::shared_ptr<SketchPlugin_Constraint>, Slvs_hConstraint>::const_iterator
- aConstrMapIter = myConstraintMap.find(theConstraint);
- std::vector<Slvs_Constraint>::iterator aConstrIter;
- if (aConstrMapIter != myConstraintMap.end())
- {
- int aConstrPos = Search(aConstrMapIter->second, myConstraints);
- aConstrIter = myConstraints.begin() + aConstrPos;
- }
-
- // Get constraint type and verify the constraint parameters are correct
- int aConstrType = getConstraintType(theConstraint);
- if (aConstrType == SLVS_C_UNKNOWN ||
- (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
- 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)
- {
- aDistance = aDistAttr->value();
- if (aConstrMapIter != myConstraintMap.end() && fabs(aConstrIter->valA - aDistance) > tolerance)
- {
- myNeedToSolve = true;
- aConstrIter->valA = aDistance;
- }
- }
-
- Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint
- for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
- {
- aConstrEnt[indAttr] = SLVS_E_UNKNOWN;
- boost::shared_ptr<ModelAPI_AttributeRefAttr> aConstrAttr =
- boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
- );
- if (!aConstrAttr) continue;
- aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr());
- }
-
- if (aConstrMapIter == myConstraintMap.end())
- {
- // Create SolveSpace constraint structure
- Slvs_Constraint aConstraint =
- Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, myWorkplane.h,
- aDistance, aConstrEnt[0], aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]);
- myConstraints.push_back(aConstraint);
- myConstraintMap[theConstraint] = aConstraint.h;
- }
- return true;
-}
-
-Slvs_hEntity SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::changeEntity(
- boost::shared_ptr<ModelAPI_Attribute> theEntity)
-{
- // If the entity is already in the group, try to find it
- std::map<boost::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator
- aEntIter = myEntityMap.find(theEntity);
- std::vector<Slvs_Param>::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise
- if (aEntIter == myEntityMap.end()) // no such entity => should be created
- aParamIter = myParams.end();
- else
- { // the entity already exists
- int aEntPos = Search(aEntIter->second, myEntities);
- int aParamPos = Search(myEntities[aEntPos].param[0], myParams);
- aParamIter = myParams.begin() + aParamPos;
- }
-
- // 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 = changeParameter(aPoint->x(), aParamIter);
- Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter);
- Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter);
-
- if (aEntIter != myEntityMap.end()) // the entity already exists
- return aEntIter->second;
-
- // New entity
- Slvs_Entity aPtEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ);
- myEntities.push_back(aPtEntity);
- myEntityMap[theEntity] = aPtEntity.h;
- 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 == SLVS_E_UNKNOWN)
- return SLVS_E_UNKNOWN;
- Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter);
- Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter);
-
- if (aEntIter != myEntityMap.end()) // the entity already exists
- return aEntIter->second;
-
- // New entity
- Slvs_Entity aPt2DEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV);
- myEntities.push_back(aPt2DEntity);
- myEntityMap[theEntity] = aPt2DEntity.h;
- return aPt2DEntity.h;
- }
-
- /// \todo Other types of entities
-
- // Unsupported or wrong entity type
- return SLVS_E_UNKNOWN;
-}
-
-Slvs_hEntity SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::changeNormal(
- boost::shared_ptr<ModelAPI_Attribute> theDirX,
- boost::shared_ptr<ModelAPI_Attribute> theDirY,
- boost::shared_ptr<ModelAPI_Attribute> theNorm)
-{
- 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 ||
- (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) ||
- (fabs(aDirY->x()) + fabs(aDirY->y()) + fabs(aDirY->z()) < tolerance))
- return SLVS_E_UNKNOWN;
-
- // 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);
- double aNormCoord[4] = {qw, qx, qy, qz};
-
- // Try to find existent normal
- std::map<boost::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator
- aEntIter = myEntityMap.find(theNorm);
- std::vector<Slvs_Param>::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise
- if (aEntIter == myEntityMap.end()) // no such entity => should be created
- aParamIter = myParams.end();
- else
- { // the entity already exists, update it
- int aEntPos = Search(aEntIter->second, myEntities);
- int aParamPos = Search(myEntities[aEntPos].param[0], myParams);
- aParamIter = myParams.begin() + aParamPos;
- }
-
- // Change parameters of the normal
- Slvs_hParam aNormParams[4];
- for (int i = 0; i < 4; i++)
- aNormParams[i] = changeParameter(aNormCoord[i], aParamIter);
-
- if (aEntIter != myEntityMap.end()) // the entity already exists
- return aEntIter->second;
-
- // Create a normal
- Slvs_Entity aNormal = Slvs_MakeNormal3d(++myEntityMaxID, myID,
- aNormParams[0], aNormParams[1], aNormParams[2], aNormParams[3]);
- myEntities.push_back(aNormal);
- myEntityMap[theNorm] = aNormal.h;
- return aNormal.h;
-}
-
-
-bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addWorkplane(
- boost::shared_ptr<SketchPlugin_Feature> theSketch)
-{
- if (myWorkplane.h || theSketch->getKind().compare("Sketch") != 0)
- return false; // the workplane already exists or the function parameter is not Sketch
-
- mySketch = theSketch;
- updateWorkplane();
- return true;
-}
-
-bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::updateWorkplane()
-{
- // Get parameters of workplane
- boost::shared_ptr<ModelAPI_Attribute> aDirX = mySketch->data()->attribute(SKETCH_ATTR_DIRX);
- boost::shared_ptr<ModelAPI_Attribute> aDirY = mySketch->data()->attribute(SKETCH_ATTR_DIRY);
- boost::shared_ptr<ModelAPI_Attribute> aNorm = mySketch->data()->attribute(SKETCH_ATTR_NORM);
- boost::shared_ptr<ModelAPI_Attribute> anOrigin = mySketch->data()->attribute(SKETCH_ATTR_ORIGIN);
- // Transform them into SolveSpace format
- Slvs_hEntity aNormalWP = changeNormal(aDirX, aDirY, aNorm);
- if (!aNormalWP) return false;
- Slvs_hEntity anOriginWP = changeEntity(anOrigin);
- if (!anOriginWP) return false;
-
- if (!myWorkplane.h)
- {
- // Create workplane
- myWorkplane = Slvs_MakeWorkplane(++myEntityMaxID, myID, anOriginWP, aNormalWP);
- // Workplane should be added to the list of entities
- myEntities.push_back(myWorkplane);
- }
- return true;
-}
-
-
-Slvs_hParam SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::changeParameter(
- const double& theParam,
- std::vector<Slvs_Param>::const_iterator& thePrmIter)
-{
- if (thePrmIter != myParams.end())
- { // Parameter should be updated
- int aParamPos = thePrmIter - myParams.begin();
- if (fabs(thePrmIter->val - theParam) > tolerance)
- {
- myNeedToSolve = true; // parameter is changed, need to resolve constraints
- myParams[aParamPos].val = theParam;
- }
- thePrmIter++;
- return myParams[aParamPos].h;
- }
-
- // Newly created parameter
- Slvs_Param aParam = Slvs_MakeParam(++myParamMaxID, myID, theParam);
- myParams.push_back(aParam);
- myNeedToSolve = true;
- // The list of parameters is changed, move iterator to the end of the list to avoid problems
- thePrmIter = myParams.end();
- return aParam.h;