1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PlaneGCSSolver_Solver.cpp
4 // Created: 14 Dec 2014
5 // Author: Artem ZHIDKOV
7 #include <PlaneGCSSolver_Solver.h>
8 #include <Events_LongOp.h>
11 PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
12 : myEquationSystem(new GCS::System),
13 myDiagnoseBeforeSolve(false),
15 myConfCollected(false),
17 myFictiveConstraint(0)
21 PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
26 void PlaneGCSSolver_Solver::clear()
28 myEquationSystem->clear();
30 myConstraints.clear();
31 myConflictingIDs.clear();
34 removeFictiveConstraint();
37 void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
39 myEquationSystem->addConstraint(theConstraint.get());
40 myConstraints[theConstraint->getTag()].insert(theConstraint);
44 void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
46 myConstraints.erase(theID);
47 if (myConstraints.empty()) {
48 myEquationSystem->clear();
49 myDOF = (int)myParameters.size();
51 myEquationSystem->clearByTag(theID);
56 double* PlaneGCSSolver_Solver::createParameter()
58 double* aResult = new double(0);
59 myParameters.push_back(aResult);
60 if (myConstraints.empty() && myDOF >= 0)
61 ++myDOF; // calculate DoF by hand if and only if there is no constraints yet
63 myDiagnoseBeforeSolve = true;
67 void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams)
69 for (int i = (int)myParameters.size() - 1; i >= 0; --i)
70 if (theParams.find(myParameters[i]) != theParams.end()) {
71 myParameters.erase(myParameters.begin() + i);
76 void PlaneGCSSolver_Solver::initialize()
78 Events_LongOp::start(this);
79 addFictiveConstraintIfNecessary();
80 if (myDiagnoseBeforeSolve)
82 myEquationSystem->declareUnknowns(myParameters);
83 myEquationSystem->initSolution();
84 Events_LongOp::end(this);
89 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
91 // clear list of conflicting constraints
92 if (myConfCollected) {
93 myConflictingIDs.clear();
94 myConfCollected = false;
97 if (myParameters.empty())
98 return STATUS_INCONSISTENT;
100 GCS::SolveStatus aResult = GCS::Success;
101 Events_LongOp::start(this);
103 aResult = (GCS::SolveStatus)myEquationSystem->solve();
105 addFictiveConstraintIfNecessary();
107 if (myDiagnoseBeforeSolve)
109 aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
111 Events_LongOp::end(this);
113 // collect information about conflicting constraints every time,
114 // sometimes solver reports about succeeded recalculation but has conflicting constraints
115 // (for example, apply horizontal constraint for a copied feature)
116 collectConflicting();
117 if (!myConflictingIDs.empty())
118 aResult = GCS::Failed;
121 if (aResult == GCS::Failed)
122 aStatus = STATUS_FAILED;
124 myEquationSystem->applySolution();
126 myDOF = myEquationSystem->dofsNumber();
130 removeFictiveConstraint();
131 myInitilized = false;
135 void PlaneGCSSolver_Solver::undo()
137 myEquationSystem->undoSolution();
140 bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
142 if (!myConfCollected)
143 const_cast<PlaneGCSSolver_Solver*>(this)->collectConflicting();
144 return myConflictingIDs.find((int)theConstraint) != myConflictingIDs.end();
147 void PlaneGCSSolver_Solver::collectConflicting()
149 GCS::VEC_I aConflict;
150 myEquationSystem->getConflicting(aConflict);
151 myConflictingIDs.insert(aConflict.begin(), aConflict.end());
153 myEquationSystem->getRedundant(aConflict);
154 myConflictingIDs.insert(aConflict.begin(), aConflict.end());
156 myConfCollected = true;
159 int PlaneGCSSolver_Solver::dof()
161 if (myDOF < 0 && !myConstraints.empty())
166 void PlaneGCSSolver_Solver::diagnose()
168 myEquationSystem->declareUnknowns(myParameters);
169 myDOF = myEquationSystem->diagnose();
170 myDiagnoseBeforeSolve = false;
173 void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary()
175 if (!myConstraints.empty() &&
176 myConstraints.find(CID_MOVEMENT) == myConstraints.end())
179 if (myFictiveConstraint)
180 return; // no need several fictive constraints
182 double* aParam = createParameter();
183 double* aFictiveParameter = new double(0.0);
185 myFictiveConstraint = new GCS::ConstraintEqual(aFictiveParameter, aParam);
186 myFictiveConstraint->setTag(CID_FICTIVE);
187 myEquationSystem->addConstraint(myFictiveConstraint);
190 void PlaneGCSSolver_Solver::removeFictiveConstraint()
192 if (myFictiveConstraint) {
193 myEquationSystem->removeConstraint(myFictiveConstraint);
194 myParameters.pop_back();
196 GCS::VEC_pD aParams = myFictiveConstraint->params();
197 for (GCS::VEC_pD::iterator anIt = aParams.begin(); anIt != aParams.end(); ++ anIt)
199 delete myFictiveConstraint;
200 myFictiveConstraint = 0;