Salome HOME
6681f2072f96824fc9d80764f2f4dd0aab2e2848
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_Solver.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    PlaneGCSSolver_Solver.cpp
4 // Created: 14 Dec 2014
5 // Author:  Artem ZHIDKOV
6
7 #include <PlaneGCSSolver_Solver.h>
8 #include <Events_LongOp.h>
9
10
11 PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
12   : myEquationSystem(new GCS::System),
13     myConfCollected(false),
14     myDOF(0)
15 {
16 }
17
18 PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
19 {
20   clear();
21 }
22
23 void PlaneGCSSolver_Solver::clear()
24 {
25   myEquationSystem->clear();
26   myParameters.clear();
27   myConstraints.clear();
28   myConflictingIDs.clear();
29   myDOF = 0;
30 }
31
32 void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
33 {
34   myEquationSystem->addConstraint(theConstraint.get());
35   myConstraints[theConstraint->getTag()].insert(theConstraint);
36   myDOF = -1;
37 }
38
39 void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
40 {
41   myConstraints.erase(theID);
42   if (myConstraints.empty()) {
43     myEquationSystem->clear();
44     myDOF = (int)myParameters.size();
45   } else {
46     myEquationSystem->clearByTag(theID);
47     myDOF = -1;
48   }
49 }
50
51 double* PlaneGCSSolver_Solver::createParameter()
52 {
53   double* aResult = new double(0);
54   myParameters.push_back(aResult);
55   if (myConstraints.empty() && myDOF >= 0)
56     ++myDOF; // calculate DoF by hand if and only if there is no constraints yet
57   return aResult;
58 }
59
60 void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams)
61 {
62   for (int i = (int)myParameters.size() - 1; i >= 0; --i)
63     if (theParams.find(myParameters[i]) != theParams.end()) {
64       myParameters.erase(myParameters.begin() + i);
65       --myDOF;
66     }
67 }
68
69 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
70 {
71   // clear list of conflicting constraints
72   if (myConfCollected) {
73     myConflictingIDs.clear();
74     myConfCollected = false;
75   }
76
77   if (myParameters.empty())
78     return STATUS_INCONSISTENT;
79
80   Events_LongOp::start(this);
81   // solve equations
82   GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
83   Events_LongOp::end(this);
84
85   GCS::VEC_I aRedundant;
86   myEquationSystem->getRedundant(aRedundant);
87   if (!aRedundant.empty()) {
88     collectConflicting();
89     if (!myConflictingIDs.empty())
90       aResult = GCS::Failed;
91   }
92
93   SolveStatus aStatus;
94   if (aResult == GCS::Failed)
95     aStatus = STATUS_FAILED;
96   else {
97     myEquationSystem->applySolution();
98     if (myDOF < 0)
99       myDOF = myEquationSystem->dofsNumber();
100     aStatus = STATUS_OK;
101   }
102
103   return aStatus;
104 }
105
106 void PlaneGCSSolver_Solver::undo()
107 {
108   myEquationSystem->undoSolution();
109 }
110
111 bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
112 {
113   if (!myConfCollected)
114     const_cast<PlaneGCSSolver_Solver*>(this)->collectConflicting();
115   return myConflictingIDs.find((int)theConstraint) != myConflictingIDs.end();
116 }
117
118 void PlaneGCSSolver_Solver::collectConflicting()
119 {
120   GCS::VEC_I aConflict;
121   myEquationSystem->getConflicting(aConflict);
122   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
123
124   myEquationSystem->getRedundant(aConflict);
125   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
126
127   myConfCollected = true;
128 }
129
130 int PlaneGCSSolver_Solver::dof()
131 {
132   if (myDOF < 0 && !myConstraints.empty())
133     solve();
134   return myDOF;
135 }
136
137 void PlaneGCSSolver_Solver::diagnose()
138 {
139   myEquationSystem->declareUnknowns(myParameters);
140   myDOF = myEquationSystem->diagnose();
141 }