]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
Salome HOME
Issue #2133: Edge with middle node constraint can be moved
[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     myDiagnoseBeforeSolve(false),
14     myInitilized(false),
15     myConfCollected(false),
16     myDOF(0)
17 {
18 }
19
20 PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
21 {
22   clear();
23 }
24
25 void PlaneGCSSolver_Solver::clear()
26 {
27   myEquationSystem->clear();
28   myParameters.clear();
29   myConstraints.clear();
30   myConflictingIDs.clear();
31   myDOF = 0;
32 }
33
34 void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
35 {
36   myEquationSystem->addConstraint(theConstraint.get());
37   myConstraints[theConstraint->getTag()].insert(theConstraint);
38   myDOF = -1;
39 }
40
41 void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
42 {
43   myConstraints.erase(theID);
44   if (myConstraints.empty()) {
45     myEquationSystem->clear();
46     myDOF = (int)myParameters.size();
47   } else {
48     myEquationSystem->clearByTag(theID);
49     myDOF = -1;
50   }
51 }
52
53 double* PlaneGCSSolver_Solver::createParameter()
54 {
55   double* aResult = new double(0);
56   myParameters.push_back(aResult);
57   if (myConstraints.empty() && myDOF >= 0)
58     ++myDOF; // calculate DoF by hand if and only if there is no constraints yet
59   else
60     myDiagnoseBeforeSolve = true;
61   return aResult;
62 }
63
64 void PlaneGCSSolver_Solver::removeParameters(const GCS::SET_pD& theParams)
65 {
66   for (int i = (int)myParameters.size() - 1; i >= 0; --i)
67     if (theParams.find(myParameters[i]) != theParams.end()) {
68       myParameters.erase(myParameters.begin() + i);
69       --myDOF;
70     }
71 }
72
73 void PlaneGCSSolver_Solver::initialize()
74 {
75   Events_LongOp::start(this);
76   if (myDiagnoseBeforeSolve)
77     diagnose();
78   myEquationSystem->declareUnknowns(myParameters);
79   myEquationSystem->initSolution();
80   Events_LongOp::end(this);
81
82   myInitilized = true;
83 }
84
85 PlaneGCSSolver_Solver::SolveStatus PlaneGCSSolver_Solver::solve()
86 {
87   // clear list of conflicting constraints
88   if (myConfCollected) {
89     myConflictingIDs.clear();
90     myConfCollected = false;
91   }
92
93   if (myParameters.empty())
94     return STATUS_INCONSISTENT;
95
96   GCS::SolveStatus aResult = GCS::Success;
97   Events_LongOp::start(this);
98   if (myInitilized) {
99     aResult = (GCS::SolveStatus)myEquationSystem->solve();
100   } else {
101     if (myDiagnoseBeforeSolve)
102       diagnose();
103     aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
104   }
105   Events_LongOp::end(this);
106
107   // collect information about conflicting constraints every time,
108   // sometimes solver reports about succeeded recalculation but has conflicting constraints
109   // (for example, apply horizontal constraint for a copied feature)
110   collectConflicting();
111   if (!myConflictingIDs.empty())
112     aResult = GCS::Failed;
113
114   SolveStatus aStatus;
115   if (aResult == GCS::Failed)
116     aStatus = STATUS_FAILED;
117   else {
118     myEquationSystem->applySolution();
119     if (myDOF < 0)
120       myDOF = myEquationSystem->dofsNumber();
121     aStatus = STATUS_OK;
122   }
123
124   myInitilized = false;
125   return aStatus;
126 }
127
128 void PlaneGCSSolver_Solver::undo()
129 {
130   myEquationSystem->undoSolution();
131 }
132
133 bool PlaneGCSSolver_Solver::isConflicting(const ConstraintID& theConstraint) const
134 {
135   if (!myConfCollected)
136     const_cast<PlaneGCSSolver_Solver*>(this)->collectConflicting();
137   return myConflictingIDs.find((int)theConstraint) != myConflictingIDs.end();
138 }
139
140 void PlaneGCSSolver_Solver::collectConflicting()
141 {
142   GCS::VEC_I aConflict;
143   myEquationSystem->getConflicting(aConflict);
144   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
145
146   myEquationSystem->getRedundant(aConflict);
147   myConflictingIDs.insert(aConflict.begin(), aConflict.end());
148
149   myConfCollected = true;
150 }
151
152 int PlaneGCSSolver_Solver::dof()
153 {
154   if (myDOF < 0 && !myConstraints.empty())
155     diagnose();
156   return myDOF;
157 }
158
159 void PlaneGCSSolver_Solver::diagnose()
160 {
161   myEquationSystem->declareUnknowns(myParameters);
162   myDOF = myEquationSystem->diagnose();
163   myDiagnoseBeforeSolve = false;
164 }