std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator aMyIter = myAttrs.begin();
for(; aMyIter != myAttrs.end(); aMyIter++) {
if (aMyIter->second->isInitialized()) {
- theTarget->attribute(aMyIter->first)->setInitialized();
+ AttributePtr aTargetAttr = theTarget->attribute(aMyIter->first);
+ if (aTargetAttr)
+ aTargetAttr->setInitialized();
}
}
}
mySketchSolver->setGroup(myID);
mySketchSolver->calculateFailedConstraints(false);
myStorage->initializeSolver(mySketchSolver);
+ mySketchSolver->prepare();
SketchSolver_SolveStatus aResult = STATUS_OK;
try {
sendMessage(EVENT_SOLVER_FAILED);
myPrevSolved = false;
}
+ mySketchSolver->undo();
return false;
}
if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET) { // solution succeeded, store results into correspondent attributes
sendMessage(EVENT_SOLVER_REPAIRED);
myPrevSolved = true;
}
- } else if (!myConstraints.empty()) {
+ } else {
+ mySketchSolver->undo();
+ if (!myConstraints.empty()) {
// Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
- getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::CONSTRAINTS());
- if (myPrevSolved) {
- // the error message should be changed before sending the message
- sendMessage(EVENT_SOLVER_FAILED);
- myPrevSolved = false;
+ getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(SketchSolver_Error::CONSTRAINTS());
+ if (myPrevSolved) {
+ // the error message should be changed before sending the message
+ sendMessage(EVENT_SOLVER_FAILED);
+ myPrevSolved = false;
+ }
}
}
void calculateFailedConstraints(bool theSic)
{ myFindFaileds = theSic; }
+ /// \brief Prepare for solving. Store initial values of parameters for undo
+ virtual void prepare() = 0;
+
/// \brief Solve the set of equations
/// \return identifier whether solution succeeded
virtual SketchSolver_SolveStatus solve() = 0;
+ /// \brief Revert solution to initial values
+ virtual void undo() = 0;
+
protected:
GroupID myGroup; ///< ID of the group to be solved
bool myFindFaileds; ///< flag to find conflicting or inappropriate constraints
(theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
setNeedToResolve(true); // the entity is new or modified
+ if (!theSolverEntity) {
+ // feature links to the empty entity, add its attributes
+ std::list<AttributePtr> aPntAttrs =
+ theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
+ for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
+ addEntity(*anAttrIt, EntityWrapperPtr());
+ }
+
myFeatureMap[theFeature] = theSolverEntity;
// block events if necessary
if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
// If the set of constraints is inconsistent,
// the failed field will contain wrong constraints
myEquationsSystem.calculateFaileds = 0;
+
+ myParamsCopy = 0;
}
SolveSpaceSolver_Solver::~SolveSpaceSolver_Solver()
if (myEquationsSystem.failed)
delete[] myEquationsSystem.failed;
myEquationsSystem.failed = 0;
+ if (myParamsCopy)
+ delete [] myParamsCopy;
+ myParamsCopy = 0;
}
void SolveSpaceSolver_Solver::setParameters(Slvs_Param* theParameters, int theSize)
default:
aStatus = STATUS_FAILED;
}
+
+ if (aStatus == STATUS_OK) {
+ // additional verification of arcs to be non-degenerated
+ if (hasDegeneratedArcs()) {
+ undo();
+ aStatus = STATUS_INCONSISTENT;
+ }
+ }
+
return aStatus;
}
+
+void SolveSpaceSolver_Solver::prepare()
+{
+ // make a copy of parameters to be able to make undo
+ if (myParamsCopy)
+ delete [] myParamsCopy;
+ myParamsCopy = new Slvs_Param[myEquationsSystem.params];
+ memcpy(myParamsCopy, myEquationsSystem.param, myEquationsSystem.params * sizeof(Slvs_Param));
+}
+
+void SolveSpaceSolver_Solver::undo()
+{
+ if (myParamsCopy) {
+ memcpy(myEquationsSystem.param, myParamsCopy, myEquationsSystem.params * sizeof(Slvs_Param));
+ delete [] myParamsCopy;
+ }
+ myParamsCopy = 0;
+}
+
+
+bool SolveSpaceSolver_Solver::hasDegeneratedArcs() const
+{
+ const double aTol2 = tolerance * tolerance;
+ double anArcPoints[3][2];
+
+ for (int anEnt = 0; anEnt < myEquationsSystem.entities; ++anEnt) {
+ const Slvs_Entity& anEntity = myEquationsSystem.entity[anEnt];
+ if (anEntity.type != SLVS_E_ARC_OF_CIRCLE)
+ continue;
+
+ for (int aPnt = 0; aPnt < 3; ++aPnt) {
+ // search point of arc
+ const int aShift = anEntity.point[aPnt] - anEntity.h;
+ int aPntInd = anEnt + aShift;
+ int aStep = 1;
+ if (myEquationsSystem.entity[aPntInd].h > anEntity.point[aPnt])
+ aStep = -1;
+ for (; aPntInd >=0 && aPntInd < myEquationsSystem.entities; aPntInd += aStep)
+ if (myEquationsSystem.entity[aPntInd].h == anEntity.point[aPnt])
+ break;
+
+ // search coordinates of the point
+ int aParamInd = myEquationsSystem.entity[aPntInd].param[0];
+ if (aParamInd >= myEquationsSystem.params) {
+ aParamInd = myEquationsSystem.params - 1;
+ aStep = -1;
+ }
+ else if ((int)myEquationsSystem.param[aParamInd].h > aParamInd)
+ aStep = -1;
+ else aStep = 1;
+
+ for (; aParamInd >=0 && aParamInd < myEquationsSystem.params; aParamInd += aStep)
+ if (myEquationsSystem.param[aParamInd].h == myEquationsSystem.entity[aPntInd].param[0])
+ break;
+ anArcPoints[aPnt][0] = myEquationsSystem.param[aParamInd].val;
+ anArcPoints[aPnt][1] = myEquationsSystem.param[aParamInd+1].val;
+ }
+
+ // check radius of arc
+ anArcPoints[1][0] -= anArcPoints[0][0];
+ anArcPoints[1][1] -= anArcPoints[0][1];
+ anArcPoints[2][0] -= anArcPoints[0][0];
+ anArcPoints[2][1] -= anArcPoints[0][1];
+ if (anArcPoints[1][0] * anArcPoints[1][0] + anArcPoints[1][1] * anArcPoints[1][1] < aTol2 ||
+ anArcPoints[2][0] * anArcPoints[2][0] + anArcPoints[2][1] * anArcPoints[2][1] < aTol2)
+ return true;
+ }
+ return false;
+}
*/
virtual SketchSolver_SolveStatus solve();
- private:
+ /// \brief Prepare for solving. Store initial values of parameters for undo
+ virtual void prepare();
+
+ /// \brief Revert solution to initial values
+ virtual void undo();
+
+private:
+ /// \brief Check whether degenerated arcs exist
+ bool hasDegeneratedArcs() const;
+
+private:
Slvs_System myEquationsSystem; ///< set of equations for solving in SolveSpace
+ Slvs_Param* myParamsCopy; ///< copy of parameters
};
#endif
aSlvsEnt.distance = anID;
else if (aSlvsEnt.point[anInd] != anID) {
aSlvsEnt.point[anInd] = anID;
+ if ((*aSIt)->baseAttribute())
+ SketchSolver_Storage::addEntity((*aSIt)->baseAttribute(), *aSIt);
isUpdated = true;
}
}