-
- // Copy constraints excluding the fixed one
- std::vector<Slvs_Constraint> aConstraints = myConstraints;
- if (myFixed != SLVS_E_UNKNOWN) {
- Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
- std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
- for (; anIt != aConstraints.end(); anIt++)
- if (anIt->h == myFixed) {
- aFixedPoint = anIt->ptA;
- aConstraints.erase(anIt);
- break;
- }
- // set dragged parameters
- int aPos = Search(aFixedPoint, myEntities);
- aSolver->setDraggedParameters(myEntities[aPos].param);
- }
- aSolver->setConstraints(aConstraints.data(), (int)aConstraints.size());
-}
-
-
-bool SolveSpaceSolver_Storage::isEqual(
- const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
-{
- // Precise checking of coincidence: verify that points have equal coordinates
- int aEnt1Pos = Search(thePoint1, myEntities);
- int aEnt2Pos = Search(thePoint2, myEntities);
- if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
- aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
- double aDist[2];
- int aParamPos;
- for (int i = 0; i < 2; i++) {
- aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
- aDist[i] = myParameters[aParamPos].val;
- aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
- aDist[i] -= myParameters[aParamPos].val;
- }
- if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
- return true;
- }
- return false;
-}
-
-
-std::vector<Slvs_hConstraint> SolveSpaceSolver_Storage::fixEntity(const Slvs_hEntity& theEntity)
-{
- std::vector<Slvs_hConstraint> aNewConstraints;
-
- int aPos = Search(theEntity, myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- switch (myEntities[aPos].type) {
- case SLVS_E_POINT_IN_2D:
- case SLVS_E_POINT_IN_3D:
- fixPoint(myEntities[aPos], aNewConstraints);
- break;
- case SLVS_E_LINE_SEGMENT:
- fixLine(myEntities[aPos], aNewConstraints);
- break;
- case SLVS_E_CIRCLE:
- fixCircle(myEntities[aPos], aNewConstraints);
- break;
- case SLVS_E_ARC_OF_CIRCLE:
- fixArc(myEntities[aPos], aNewConstraints);
- break;
- default:
- break;
- }
- }
-
- return aNewConstraints;
-}
-
-void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- Slvs_Constraint aConstraint;
- Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
- bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
- bool isForceUpdate = (isFixed /*&& isTemporary(aConstrID)*/);
- if (!isForceUpdate) { // create new constraint
- if (isFixed) return;
- aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
- 0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- aConstraint.h = addConstraint(aConstraint);
- theCreated.push_back(aConstraint.h);
- } else { // update already existent constraint
- if (!isFixed || aConstrID == SLVS_E_UNKNOWN)
- return;
- int aPos = Search(aConstrID, myConstraints);
- if (aPos >= 0 && aPos < (int)myConstraints.size())
- myConstraints[aPos].ptA = thePoint.h;
- }
-}
-
-void SolveSpaceSolver_Storage::fixLine(const Slvs_Entity& theLine,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- Slvs_Entity aPoint[2] = {
- getEntity(theLine.point[0]),
- getEntity(theLine.point[1])
- };
-
- Slvs_Constraint anEqual;
- if (isAxisParallel(theLine.h)) {
- // Fix one point and a line length
- Slvs_hConstraint aFixed;
- if (!isPointFixed(theLine.point[0], aFixed, true) &&
- !isPointFixed(theLine.point[1], aFixed, true))
- fixPoint(aPoint[0], theCreated);
- if (!isUsedInEqual(theLine.h, anEqual)) {
- // Check the distance is not set yet
- std::vector<Slvs_Constraint>::const_iterator aDistIt = myConstraints.begin();
- for (; aDistIt != myConstraints.end(); ++aDistIt)
- if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) &&
- ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) ||
- (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0])))
- return;
- // Calculate distance between points on the line
- double aCoords[4];
- for (int i = 0; i < 2; i++)
- for (int j = 0; j < 2; j++) {
- Slvs_Param aParam = getParameter(aPoint[i].param[j]);
- aCoords[2*i+j] = aParam.val;
- }
-
- double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) +
- (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
- // fix line length
- Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group,
- SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength,
- theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- aDistance.h = addConstraint(aDistance);
- theCreated.push_back(aDistance.h);
- }
- return;
- }
- else if (isUsedInEqual(theLine.h, anEqual)) {
- // Check another entity of Equal is already fixed
- Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
- if (isEntityFixed(anOtherEntID, true)) {
- // Fix start point of the line (if end point is not fixed yet) ...
- Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
- bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true);
- if (isFixed == SLVS_E_UNKNOWN)
- fixPoint(aPoint[0], theCreated);
- // ... and create fixed point lying on this line
- Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
- // Firstly, search already fixed point on line
- bool isPonLineFixed = false;
- Slvs_hEntity aFixedPoint;
- std::vector<Slvs_Constraint>::const_iterator aPLIter = myConstraints.begin();
- for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter)
- if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) {
- isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID);
- aFixedPoint = aPLIter->ptA;
- }
-
- if (isPonLineFixed) { // update existent constraint
- copyEntity(aPointToCopy, aFixedPoint);
- } else { // create new constraint
- Slvs_hEntity aCopied = copyEntity(aPointToCopy);
- Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE,
- theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
- aPonLine.h = addConstraint(aPonLine);
- theCreated.push_back(aPonLine.h);
- fixPoint(getEntity(aCopied), theCreated);
- }
- return;
- }
- }
-
- // Fix both points
- for (int i = 0; i < 2; i++)
- fixPoint(aPoint[i], theCreated);
-}
-
-void SolveSpaceSolver_Storage::fixCircle(const Slvs_Entity& theCircle,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- bool isFixRadius = true;
- // Verify the arc is under Equal constraint
- Slvs_Constraint anEqual;
- if (isUsedInEqual(theCircle.h, anEqual)) {
- // Check another entity of Equal is already fixed
- Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
- if (isEntityFixed(anOtherEntID, true))
- isFixRadius = false;
- }
-
- fixPoint(getEntity(theCircle.point[0]), theCreated);
-
- if (isFixRadius) {
- // Search the radius is already fixed
- std::vector<Slvs_Constraint>::const_iterator aDiamIter = myConstraints.begin();
- for (; aDiamIter != myConstraints.end(); ++aDiamIter)
- if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h)
- return;
-
- // Fix radius of a circle
- const Slvs_Entity& aRadEnt = getEntity(theCircle.distance);
- double aRadius = getParameter(aRadEnt.param[0]).val;
- Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER,
- theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN);
- aFixedR.h = addConstraint(aFixedR);
- theCreated.push_back(aFixedR.h);
- }