Minsky: 3.17.0
minsky::anonymous_namespace{wire.cc} Namespace Reference

Functions

vector< pair< float, float > > allHandleCoords (vector< float > coords)
 
vector< pair< float, float > > toCoordPair (vector< float > coords)
 
vector< vector< float > > constructTriDiag (int length)
 
vector< pair< float, float > > constructTargetVector (int n, const vector< pair< float, float >> &knots)
 
vector< pair< float, float > > computeControlPoints (vector< vector< float >> triDiag, const vector< pair< float, float >> &knots, vector< pair< float, float >> target)
 
bool segNear (float x0, float y0, float x1, float y1, float x, float y)
 
float d2 (float x0, float y0, float x1, float y1)
 

Function Documentation

◆ allHandleCoords()

vector<pair<float,float> > minsky::anonymous_namespace{wire.cc}::allHandleCoords ( vector< float >  coords)

Definition at line 150 of file wire.cc.

Referenced by minsky::Wire::near().

150  {
151 
152  vector<pair<float,float>> points(coords.size()-1);
153 
154  for (size_t i = 0; i < points.size(); i++) {
155  if (i%2 == 0) {
156  points[i].first = coords[i];
157  points[i].second = coords[i+1];
158  }
159  else {
160  points[i].first = 0.5*(coords[i-1]+coords[i+1]);
161  points[i].second = 0.5*(coords[i]+coords[i+2]);
162  }
163  }
164 
165  return points;
166  }
Here is the caller graph for this function:

◆ computeControlPoints()

vector<pair<float,float> > minsky::anonymous_namespace{wire.cc}::computeControlPoints ( vector< vector< float >>  triDiag,
const vector< pair< float, float >> &  knots,
vector< pair< float, float >>  target 
)

Thomas' algorithm for solving a matrix equation \(Ac=k\) is based on LU-decomposition into \(LUc=k\) where \(L\) is lower triangular and \(U\) is upper triangular. The matrix equation is solved by setting \(Uc = k'\) and then solving \(Lk' = k\) for \(k'\) first, and subsequently \(Uc\) for \(c\).

There are two steps in this calculation. Step 1 involves simultaneously decomposing \(A = LU\) and solving \(Lk'=k\) for \(k'\) in a forward sweep, with \(Uc=k'\) as result. In step 2, \(Uc=k'\) is solved for \(c\) in a backward sweep. The calculation goes as follows for a small system:

\[ \left(\begin{array}{ccc} b_1 & a_1 & 0 \\ d_1 & b_2 & a_2 \\ 0 & d_2 & b_3 \end{array}\right) \left(\begin{array}{c} c_1 \\ c_2 \\ c_3 \end{array}\right) = \left(\begin{array}{c} k_1 \\ k_2 \\ k_3 \end{array}\right) \]

Forward sweep: row 1:

\( b_1c_1+a_1c_2 = k_1 \)

\( c_1+\frac{c_1}{b_1}c_2 = \frac{k_1}{b_1} \) after dividing through by \(b_1\)

Rewrite row 1 as \( c_1 + \alpha_1c_2 = k'_1\), where \(\alpha_1=\frac{c_1}{b_1}\) and \(k'_1 = \frac{k_1}{b_1}\)

row 2:

\( d_1c_1+b_2c_2+a_2c_3 = k_2 \)
Now eliminate the first term of this equation by subtracting \(d_1 \times\) row 1 from row 2, yielding:

\( (b_2 - d_1\alpha_1)c_2 + a_2c_3 = k_2 - d_1k'_1 \)

Then, dividing through by \((b_2 - d_1\alpha_1)\) and rewriting leads to:

\( c_2 + \alpha_2c_3 = k'_2 \), where \(\alpha_2 = \frac{a_2}{b_2 - d_1\alpha_1}\) and \(k'_2 = \frac{k_2 - d_1k'_1}{b_2 - d_1\alpha_1}\)

row 3:

Finally, subtracting \(d_2 \times\) row 2 from row 3, dividing through by \((b_3-d_2\alpha_2)\), and rewriting, yields:

\( c_3 = k'_3 \), where \(k'_3 = \frac{k_3-d_2k'2}{b_3 - d_2\alpha_2}\)

At this point, the matrix equation has been reduced to

\[ \left(\begin{array}{ccc} 1 & \alpha_1 & 0 \\ 0 & 1 & \alpha_2 \\ 0 & 0 & 1 \end{array}\right) \left(\begin{array}{c} c_1 \\ c_2 \\ c_3 \end{array}\right) = \left(\begin{array}{c} k'_1 \\ k'_2 \\ k'_3 \end{array}\right) \]


In this form, one can solve for the \(c_i\) in terms of \(k'_i\) directly by sweeping backwards through the matrix equation.

(Source: http://www.industrial-maths.com/ms6021_thomas.pdf)

Definition at line 283 of file wire.cc.

Referenced by minsky::Wire::draw().

283  {
284 
285  assert(knots.size() > 2);
286 
287  const size_t n = knots.size() - 1;
288 
289  vector<pair<float,float>> result(2*n);
290 
291  // Vector of knots k' after Thomas' algorithm is applied to the initial system Ac = k
292  vector<pair<float,float>> newTarget(n);
293 
294  // Matrix A' after Thomas' algorithm is applied to the initial system Ac = k
295  vector<vector<float>> newTriDiag(n,vector<float>(n));
296 
297  // forward sweep for control points c_i,0:
298  newTriDiag[0][1] = triDiag[0][1]/ triDiag[0][0];
299 
300  newTarget[0].first = target[0].first*(1.0 / triDiag[0][0]);
301  newTarget[0].second = target[0].second*(1.0 / triDiag[0][0]);
302 
303 
304  for (size_t i = 1; i < n-1; i++)
305  for (size_t j = 0; j < n; j++)
306  if (i == j-1)
307  newTriDiag[i][j] = triDiag[i][j] / (triDiag[i][i] - triDiag[i][j-2] * newTriDiag[i-1][j-1]);
308 
309  for (size_t i = 1; i < n; i++)
310  for (size_t j = 0; j < n; j++) {
311  if (i == j + 1)
312  {
313  const float targetScale = 1.0/(triDiag[i][i] - triDiag[i][j] * newTriDiag[i-1][j+1]);
314  newTarget[i].first = (target[i].first-(newTarget[i-1].first*(triDiag[i][j])))*(targetScale);
315  newTarget[i].second = (target[i].second-(newTarget[i-1].second*(triDiag[i][j])))*(targetScale);
316  }
317  }
318 
319  // backward sweep for control points c_i,0:
320  result[n-1].first = newTarget[n-1].first;
321  result[n-1].second = newTarget[n-1].second;
322 
323  for (int i = n-2; i >= 0; i--)
324  for (int j = n-1; j >= 0; j--) {
325  if (i == j-1)
326  {
327  result[i].first = newTarget[i].first-(newTriDiag[i][j]*result[i+1].first);
328  result[i].second = newTarget[i].second-(newTriDiag[i][j]*result[i+1].second);
329  }
330  }
331 
332  // calculate remaining control points c_i,1 directly:
333  for (size_t i = 0; i < n-1; i++) {
334  result[n+i].first = 2.0*knots[i+1].first-(result[i+1].first);
335  result[n+i].second = 2.0*knots[i+1].second-(result[i+1].second);
336  }
337 
338  result[2*n-1].first = 0.5*(knots[n].first+(result[n-1].first));
339  result[2*n-1].second = 0.5*(knots[n].second+(result[n-1].second));
340 
341  return result;
342  }
Here is the caller graph for this function:

◆ constructTargetVector()

vector<pair<float,float> > minsky::anonymous_namespace{wire.cc}::constructTargetVector ( int  n,
const vector< pair< float, float >> &  knots 
)

Definition at line 208 of file wire.cc.

Referenced by minsky::Wire::draw().

208  {
209 
210  assert(knots.size() > 2);
211 
212  vector<pair<float,float>> result(n);
213 
214  result[0].first = knots[0].first+2.0*knots[1].first;
215  result[0].second = knots[0].second+2.0*knots[1].second;
216 
217  for (int i = 1; i < n - 1; i++) {
218  result[i].first = 2.0*(2.0*knots[i].first+(knots[i+1].first));
219  result[i].second = 2.0*(2.0*knots[i].second+(knots[i+1].second));
220  }
221 
222  result[result.size() - 1].first = 8.0*knots[n-1].first+knots[n].first;
223  result[result.size() - 1].second = 8.0*knots[n-1].second+knots[n].second;
224 
225  return result;
226  }
Here is the caller graph for this function:

◆ constructTriDiag()

vector<vector<float> > minsky::anonymous_namespace{wire.cc}::constructTriDiag ( int  length)

Definition at line 181 of file wire.cc.

Referenced by minsky::Wire::draw().

182  {
183  vector<vector<float>> result(length,vector<float>(length));
184 
185  for (int i = 0; i < length; i++) // rows
186  for (int j = 0; j < length; j++) { // columns
187 
188  //construct upper diagonal
189  if (j > 0 && i == j-1 && i < length-1) result[i][j] = 1.0;
190  //construct main diagonal
191  else if (i == j) {
192  if (i == 0) result[i][j] = 2.0;
193  else if (i < length-1) result[i][j] = 4.0;
194  else if (i == length-1) result[i][j] = 7.0;
195  }
196  //construct lower diagonal
197  else if (i == j+1) {
198  if (j < length-2) result[i][j] = 1.0;
199  else if (j == length-2) result[i][j] = 2.0;
200  }
201  else result[i][j] = 0.0;
202  }
203 
204  return result;
205  }
Here is the caller graph for this function:

◆ d2()

float minsky::anonymous_namespace{wire.cc}::d2 ( float  x0,
float  y0,
float  x1,
float  y1 
)
inline

Definition at line 564 of file wire.cc.

References minsky::sqr().

Referenced by minsky::Wire::deleteHandle(), minsky::ScalarEvalOp::deriv(), minsky::Wire::near(), minsky::Wire::nearestHandle(), and segNear().

565  {return sqr(x1-x0)+sqr(y1-y0);}
T sqr(T x)
Definition: geometry.h:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ segNear()

bool minsky::anonymous_namespace{wire.cc}::segNear ( float  x0,
float  y0,
float  x1,
float  y1,
float  x,
float  y 
)

Definition at line 557 of file wire.cc.

References d2(), minsky::sqr(), and MathDAG::sqrt().

Referenced by minsky::Wire::near().

558  {
559  const float d=sqrt(sqr(x1-x0)+sqr(y1-y0));
560  const float d1=sqrt(sqr(x-x0)+sqr(y-y0)), d2=sqrt(sqr(x-x1)+sqr(y-y1));
561  return d1+d2<=d+5;
562  }
Expr sqrt(const Expr &x)
Definition: expr.h:153
T sqr(T x)
Definition: geometry.h:36
float d2(float x0, float y0, float x1, float y1)
Definition: wire.cc:564
Here is the call graph for this function:
Here is the caller graph for this function:

◆ toCoordPair()

vector<pair<float,float> > minsky::anonymous_namespace{wire.cc}::toCoordPair ( vector< float >  coords)

Definition at line 169 of file wire.cc.

Referenced by minsky::Wire::draw().

169  {
170  vector<pair<float,float>> points(coords.size()/2);
171 
172  for (size_t i = 0; i < coords.size(); i++)
173  if (i%2 == 0) {
174  points[i/2].first = coords[i];
175  points[i/2].second = coords[i+1];
176  }
177  return points;
178  }
Here is the caller graph for this function: