vrecko
virtual reality framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Solver.h
Go to the documentation of this file.
1 #pragma once
2 #ifndef __SOLVER_H
3 #define __SOLVER_H
4 
5 #include <osg/Vec2d>
6 #include <osg/Vec3d>
7 #include <osg/Quat>
8 
9 #include <list>
10 
11 namespace ht
12 {
13 
14  /*************************************************************
15  ** Variable - base class to all variables providing
16  ** numerical calculation of their partial derivatives
17  ** To calculate parital derivative of a function, set
18  ** delta to value of step 'h' of numerical approximation
19  ** using function SetDelta. GetValueInFunction should now
20  ** return value of this variable after adding the delta.
21  ** To add delta to the variable itself, call AddDelta.
22  *************************************************************/
23  class Variable
24  {
25  public:
26  virtual ~Variable() {};
27 
28  virtual int GetVariablesCount() = 0; // Returns number of derivable subvariables
29  virtual void SetDelta(int variable, double delta) = 0; // Variable starts behaving like "var + delta" in functions, but its value itself does not change
30  virtual void AddDelta(int variable, double delta) = 0; // Adds delta to variable
31  virtual void ResetDelta() = 0; // Resets delta to zero
32 
33  // VariableType GetValue(); // Returns value of the variable
34  // VariableType GetValueInFunction(); // Returns value of the variable in function
35  };
36 
37  class VariableVec3: public Variable
38  {
39  private:
40  osg::Vec3d _value;
41  osg::Vec3d _delta;
42  public:
43  VariableVec3(): _value(0.0, 0.0, 0.0), _delta(0.0, 0.0, 0.0) {}
44  VariableVec3(const VariableVec3 &v): _value(v._value), _delta(v._delta) {}
45 
47  { _value = v._value; _delta = v._delta; return *this; }
48 
49  virtual int GetVariablesCount() override
50  { return 3; }
51  virtual void SetDelta(int variable, double delta) override
52  {
53  switch (variable)
54  {
55  case 0: _delta = osg::Vec3d(delta, 0.0, 0.0); break;
56  case 1: _delta = osg::Vec3d(0.0, delta, 0.0); break;
57  case 2: _delta = osg::Vec3d(0.0, 0.0, delta); break;
58  }
59  }
60  virtual void AddDelta(int variable, double delta) override
61  {
62  switch (variable)
63  {
64  case 0: _value += osg::Vec3d(delta, 0.0, 0.0); break;
65  case 1: _value += osg::Vec3d(0.0, delta, 0.0); break;
66  case 2: _value += osg::Vec3d(0.0, 0.0, delta); break;
67  }
68  }
69  virtual void ResetDelta() override
70  {
71  _delta = osg::Vec3d(0.0, 0.0, 0.0);
72  }
73 
74  void SetValue(osg::Vec3d v) { _value = v; }
75  osg::Vec3d GetValue() { return _value; }
76  osg::Vec3d GetValueInFunction() { return _value + _delta; }
77  };
78 
79  class VariableVec2: public Variable
80  {
81  private:
82  osg::Vec2d _value;
83  osg::Vec2d _delta;
84  public:
85  VariableVec2(): _value(0.0, 0.0), _delta(0.0, 0.0) {}
86  VariableVec2(const VariableVec2 &v): _value(v._value), _delta(v._delta) {}
87 
89  { _value = v._value; _delta = v._delta; return *this; }
90 
91  virtual int GetVariablesCount() override
92  { return 2; }
93  virtual void SetDelta(int variable, double delta) override
94  {
95  switch (variable)
96  {
97  case 0: _delta = osg::Vec2d(delta, 0.0); break;
98  case 1: _delta = osg::Vec2d(0.0, delta); break;
99  }
100  }
101  virtual void AddDelta(int variable, double delta) override
102  {
103  switch (variable)
104  {
105  case 0: _value += osg::Vec2d(delta, 0.0); break;
106  case 1: _value += osg::Vec2d(0.0, delta); break;
107  }
108  }
109  virtual void ResetDelta() override
110  {
111  _delta = osg::Vec2d(0.0, 0.0);
112  }
113 
114  void SetValue(osg::Vec2d v) { _value = v; }
115  osg::Vec2d GetValue() { return _value; }
116  osg::Vec2d GetValueInFunction() { return _value + _delta; }
117  };
118 
119  class VariableFloat: public Variable
120  {
121  private:
122  double _value;
123  double _delta;
124  public:
125  VariableFloat(): _value(0.0), _delta(0.0) {}
126  VariableFloat(const VariableFloat &f): _value(f._value), _delta(f._delta) {}
127 
129  { _value = f._value; _delta = f._delta; return *this; }
130 
131  virtual int GetVariablesCount() override
132  { return 1; }
133  virtual void SetDelta(int variable, double delta) override
134  {
135  switch (variable)
136  {
137  case 0: _delta = delta; break;
138  }
139  }
140  virtual void AddDelta(int variable, double delta) override
141  {
142  switch (variable)
143  {
144  case 0: _value += delta; break;
145  }
146  }
147  virtual void ResetDelta() override
148  {
149  _delta = 0.0;
150  }
151 
152  void SetValue(double v) { _value = v; }
153  double GetValue() { return _value; }
154  double GetValueInFunction() { return _value + _delta; }
155  };
156 
157  class VariableQuat: public Variable
158  {
159  private:
160  osg::Quat _value;
161  osg::Quat _delta;
162  public:
163  VariableQuat(): _value(0.0, osg::Vec3d(1.0, 0.0, 0.0)), _delta(0.0, osg::Vec3d(1.0, 0.0, 0.0)) {}
164  VariableQuat(const VariableQuat &v): _value(v._value), _delta(v._delta) {}
165 
167  { _value = v._value; _delta = v._delta; return *this; }
168 
169  virtual int GetVariablesCount() override
170  { return 3; }
171  virtual void SetDelta(int variable, double delta) override
172  {
173  switch (variable)
174  {
175  case 0: _delta = osg::Quat(delta, osg::Vec3d(1.0, 0.0, 0.0)); break;
176  case 1: _delta = osg::Quat(delta, osg::Vec3d(0.0, 1.0, 0.0)); break;
177  case 2: _delta = osg::Quat(delta, osg::Vec3d(0.0, 0.0, 1.0)); break;
178  }
179  }
180  virtual void AddDelta(int variable, double delta) override
181  {
182  switch (variable)
183  {
184  case 0: _value = _value * osg::Quat(delta, osg::Vec3d(1.0, 0.0, 0.0)); _value /= _value.length(); break;
185  case 1: _value = _value * osg::Quat(delta, osg::Vec3d(0.0, 1.0, 0.0)); _value /= _value.length(); break;
186  case 2: _value = _value * osg::Quat(delta, osg::Vec3d(0.0, 0.0, 1.0)); _value /= _value.length(); break;
187  }
188  }
189  virtual void ResetDelta() override
190  {
191  _delta = osg::Quat(0.0, osg::Vec3d(1.0, 0.0, 0.0));
192  }
193 
194  void SetValue(osg::Quat v) { _value = v; }
195  osg::Quat GetValue() { return _value; }
196  osg::Quat GetValueInFunction() { return _value * _delta; }
197  };
198 
199  /*********************************************
200  ** Function - base class for any function.
201  ** The most important method is Evaluate,
202  ** which returns value of the Function
203  ** (including valud of delta).
204  *********************************************/
205  class Function
206  {
207  protected:
208  // Returns distance of point v from line (l1,l2)
209  double _dist_line(osg::Vec3d v, osg::Vec3d l1, osg::Vec3d l2)
210  {
211  // According to WolframAlpha, distance of point 'v' from line 'l1 l2' is
212  // d = |(v-l1)cross(v-l2)| / |l1-l2|
213  double denom = (l1-l2).length();
214  double numer = ((v-l1) ^ (v-l2)).length();
215  if (denom < 1e-9) return (v-l2).length();
216  if (numer < 1e-9) return 0.00;
217  return numer / denom;
218  }
219  double _dist_line2(osg::Vec3d v, osg::Vec3d l1, osg::Vec3d l2)
220  {
221  return _dist_line(v, l1, l2) * _dist_line(v, l1, l2);
222  }
223  public:
224  virtual double Evaluate() = 0;
225  };
226 
227  typedef std::list<Function *> ListOfFunctions;
228  typedef std::list<Variable *> ListOfVariables;
229 
230  // Finds a minimum of the sum of functions in list of functions 'fcns'
231  // changing value of variables in list 'vars'
232  void solve(ListOfFunctions &fcns, ListOfVariables &vars, double start_step = 0.01, double next_step_scale = 0.8, double min_step_size = 1e-6);
233 
234 }
235 
236 #endif // __SOLVER_H