mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-30 03:30:34 +02:00
interpolation graphs
This commit is contained in:
@@ -12,6 +12,7 @@ var BoundingBox = React.createClass({
|
||||
},
|
||||
|
||||
bindKnots: function(owner, knots, ref) {
|
||||
console.log(`binding knots for ${ref}`);
|
||||
this.refs[ref].bindKnots(owner, knots);
|
||||
},
|
||||
|
||||
@@ -24,63 +25,59 @@ var BoundingBox = React.createClass({
|
||||
<section>
|
||||
<SectionHeader {...this.props} />
|
||||
|
||||
<p>No discussion on Bezier curves is complete without also giving mention of that other
|
||||
beast in the curve design space: B-Splines. Easily confused to mean Bezier splines, that's
|
||||
<p>No discussion on Bézier curves is complete without also giving mention of that other
|
||||
beast in the curve design space: B-Splines. Easily confused to mean Bézier splines, that's
|
||||
not actually what they are; they are "basis function" splines, which makes a lot of difference,
|
||||
which we'll be looking at in this section. We're not going to dive as deep into B-splines as
|
||||
we have for Bezier curves (that would be an entire primer on its own) but we'll be looking at
|
||||
which we'll be looking at in this section. We're not going to dive as deep into B-Splines as
|
||||
we have for Bézier curves (that would be an entire primer on its own) but we'll be looking at
|
||||
how B-Splines work, what kind of maths is involved in computing them, and how to draw them
|
||||
based on a number of parameters that you can pick for individual B-Splines.</p>
|
||||
|
||||
<p>First off: B-Splines are "piecewise polynomial interpolation curves", where the "single curve"
|
||||
<p>First off: B-Splines are <a href="https://en.wikipedia.org/wiki/Piecewise">"piecewise polynomial interpolation curves"</a>, where the "single curve"
|
||||
is built by performing polynomial interpolation over a set of points, using a sliding window
|
||||
of a fixed number of points. For instance, a "cubic" B-Spline defined by twelve points will
|
||||
have its curve built by evaluating the polynomial interpolation of four points, and the curve
|
||||
can be treated as a lot of different sections, each controlled by four points at a time, such
|
||||
that the full curve consists of smoothly connected sections defined by points {1,2,3,4}, {2,3,4,5},
|
||||
..., {8,9,10,11}, and finally {9,10,11,12} for eight sections.</p>
|
||||
..., {8,9,10,11}, and finally {9,10,11,12}, for eight sections.</p>
|
||||
|
||||
<p>What do they look like? They look like this! Simply click to place some point, with the
|
||||
stipulation that you need at least four point to see any curve. More than four points simply
|
||||
draws a longer B-spline curve.</p>
|
||||
<p>What do they look like? They look like this! .. okay that's an empty graph, but simply
|
||||
click to place some point, with the stipulation that you need at least four point to see
|
||||
any curve. More than four points simply draws a longer B-Spline curve:</p>
|
||||
|
||||
<BSplineGraphic sketch={require('./basic-sketch')} />
|
||||
|
||||
<p>The important part to notice here is that we are <strong>not</strong> doing the same thing
|
||||
with B-Splines that we do for poly-Beziers or Catmull-Rom curves: both of the latter simply
|
||||
with B-Splines that we do for poly-Béziers or Catmull-Rom curves: both of the latter simply
|
||||
define new sections as literally "new sections based on new points", so a 12 point cubic
|
||||
poly-Bezier curve is actually impossible, because we start with a four point curve, and then
|
||||
poly-Bézier curve is actually impossible, because we start with a four point curve, and then
|
||||
add three more points for each section that follows, so we can only have 4, 7, 10, 13, 16, etc
|
||||
point Poly-Beziers. Similarly, while Catmull-Rom curves can grow by adding single points, this
|
||||
addition of a single point introduces three implicit Bezier points. Cubic B-Splines, on the other
|
||||
point Poly-Béziers. Similarly, while Catmull-Rom curves can grow by adding single points, this
|
||||
addition of a single point introduces three implicit Bézier points. Cubic B-Splines, on the other
|
||||
hand, are smooth interpolations of <em>each possible curve involving four consecutive points</em>,
|
||||
such that at any point along the curve except for our start and end points, our on-curve
|
||||
coordinate is defined by four control points.</p>
|
||||
|
||||
{
|
||||
// <BSplineGraphic sketch={require('./interpolation-graph')} />
|
||||
}
|
||||
|
||||
<p>Consider the difference to be this:</p>
|
||||
|
||||
<ul>
|
||||
<li>for Bezier curves, the curve is defined as an interpolation of points, but:</li>
|
||||
<li>for Bézier curves, the curve is defined as an interpolation of points, but:</li>
|
||||
<li>for B-Splines, the curve is defined as an interpolation of <em>curves</em>.</li>
|
||||
</ul>
|
||||
|
||||
<p>In order to make this interpolation of curves work, the maths is necessarily more complex
|
||||
than the maths for Bezier curves, so let's have a look at how things work.</p>
|
||||
than the maths for Bézier curves, so let's have a look at how things work.</p>
|
||||
|
||||
<h2>
|
||||
How to compute a B-Spline curve: some maths
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Given a B-spline of degree <code>d</code> and thus order <code>k=d+1</code> (so a quadratic
|
||||
B-spline is degree 2 and order 3, a cubic B-spline is degree 3 and order 4, etc) and <code>n</code> control
|
||||
Given a B-Spline of degree <code>d</code> and thus order <code>k=d+1</code> (so a quadratic
|
||||
B-Spline is degree 2 and order 3, a cubic B-Spline is degree 3 and order 4, etc) and <code>n</code> control
|
||||
points <code>P<sub>0</sub></code> through <code>P<sub>n-1</sub></code>, we can compute a
|
||||
point on the curve for some value <code>t</code> in the interval [0,1] (where 0 is the start
|
||||
of the curve, and 1 the end, just like for Bezier curves), by evaluting the following function:
|
||||
of the curve, and 1 the end, just like for Bézier curves), by evaluting the following function:
|
||||
</p>
|
||||
|
||||
<p>\[
|
||||
@@ -88,24 +85,20 @@ var BoundingBox = React.createClass({
|
||||
\]</p>
|
||||
|
||||
<p>
|
||||
Which, honestly, doesn't tell us all that much. All we can see is that a point on a B-spline curve
|
||||
Which, honestly, doesn't tell us all that much. All we can see is that a point on a B-Spline curve
|
||||
is defined as "a mix of all the control points, weighted somehow", where the weighting is achieved
|
||||
through the <em>N(...)</em>em> function, subscipted with an obvious parameter <code>i</code>, which
|
||||
through the <em>N(...)</em> function, subscipted with an obvious parameter <code>i</code>, which
|
||||
comes from our summation, and some magical parameter <code>k</code>. So we need to know two things:
|
||||
1: what does N(t) do, and 2: what is that <code>k</code>? Let's cover both, in reverse order.
|
||||
1. what does N(t) do, and 2. what is that <code>k</code>? Let's cover both, in reverse order.
|
||||
</p>
|
||||
|
||||
<p>The parameter <code>k</code> represents the "knot interval" over which a section of curve is defined.
|
||||
As we learned earlier, a B-spline curve is itself an interpoliation of curves, and we can treat each
|
||||
As we learned earlier, a B-Spline curve is itself an interpoliation of curves, and we can treat each
|
||||
transition where a control point starts or tops influencing the total curvature as a "knot on the curve".
|
||||
Doing so for a degree <code>d</code> B-spline with <code>n</code> control point gives us <code>d + n +
|
||||
Doing so for a degree <code>d</code> B-Spline with <code>n</code> control point gives us <code>d + n +
|
||||
1</code> knots, defining <code>d + n</code> intervals along the curve, and it is these intervals that
|
||||
the above <code>k</code> subscript to the N() function applies to.</p>
|
||||
|
||||
{
|
||||
// <p>SHOW KNOTS ON THE INTERPOLATION GRAPH HERE</p>
|
||||
}
|
||||
|
||||
<p>Then the N() function itself. What does it look like?</p>
|
||||
|
||||
<p>\[
|
||||
@@ -114,8 +107,8 @@ var BoundingBox = React.createClass({
|
||||
|
||||
<p>
|
||||
So this is where we see the interpolation: N(t) for an (i,k) pair (that is, for a step in the above summation,
|
||||
on a specific knot interval) is a mix between N(t) for (i,k-1) and N(t) for (i+1,k-1), so we see that is a
|
||||
recursive iteration where <code>i</code> goes up, and <code>k</code> goes down, so it seem reasonable to
|
||||
on a specific knot interval) is a mix between N(t) for (i,k-1) and N(t) for (i+1,k-1), so we see that this is
|
||||
a recursive iteration where <code>i</code> goes up, and <code>k</code> goes down, so it seem reasonable to
|
||||
expect that this recursion has to stop at some point; obviously, it does, and specifically it does so for
|
||||
the following <code>i</code>/<code>k</code> values:
|
||||
</p>
|
||||
@@ -146,7 +139,7 @@ var BoundingBox = React.createClass({
|
||||
</p>
|
||||
|
||||
<p>
|
||||
People far smarter than us have looked at this work, and two in particular --<a href="">Cox</a> and <a href="">de Boor</a>-- came
|
||||
People far smarter than us have looked at this work, and two in particular —<a href="http://www.npl.co.uk/people/maurice-cox">Maurice Cox</a> and <a href="https://en.wikipedia.org/wiki/Carl_R._de_Boor">Carl de Boor</a>— came
|
||||
to a mathematically pleasing solution: to compute a point P(t), we can compute this point by
|
||||
evaluating <em>d(t)</em> on a curve section between knots <em>i</em> and <em>i+1</em>:
|
||||
</p>
|
||||
@@ -209,7 +202,7 @@ var BoundingBox = React.createClass({
|
||||
|
||||
<p>
|
||||
One thing we need to keep in mind is that we're working with a spline that is contrained by its control points,
|
||||
so even though the \(d^k_i\) values are zero or one at the lowest level, they are really "zero or one, times their
|
||||
so even though the <code>d(..., k)</code> values are zero or one at the lowest level, they are really "zero or one, times their
|
||||
respective control point", so in the next section you'll see the algorithm for running through the computation in
|
||||
a way that starts with a copy of the control point vector and then works its way up to that single point:
|
||||
that's pretty essential!
|
||||
@@ -224,6 +217,33 @@ var BoundingBox = React.createClass({
|
||||
we start with and simply update them as we move up the triangle. So, let's implement that!
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
Cool, cool... but I don't know what to do with that information
|
||||
</h2>
|
||||
|
||||
<p>I know, this is pretty mathy, so let's have a look at what happens when we change parameters here. We can't change
|
||||
the maths for the interpolation functions, so that gives us only one way to control what happens here: the knot vector
|
||||
itself. As such, let's look at the graph that shows the interpolation functions for a cubic B-Spline with seven points
|
||||
with a uniform knot vector (so we see seven identical functions), representing how much each point (represented by
|
||||
one function each) influences the total curvature, given our knot values. And, because exploration is the key to
|
||||
discovery, let's make the knot vector a thing we can actually manipulate. Normally a proper knot vector has a constraint
|
||||
that any value is strictly equal to, or larger than the previous ones, but screw it this is programming, let's
|
||||
ignore that hard restriction and just mess with the knots however we like.</p>
|
||||
|
||||
<div className="two-column">
|
||||
<KnotController ref="interpolation-graph" />
|
||||
<BSplineGraphic sketch={require('./interpolation-graph')} controller={(owner, knots) => this.bindKnots(owner, knots, "interpolation-graph")}/>
|
||||
</div>
|
||||
|
||||
<p>Changing the values in the knot vector changes how much each point influences the total curvature
|
||||
(with some clever knot value manipulation, we can even make the influence of certain points disappear
|
||||
entirely!), so we can see that while the control points define the hull inside of which we're going
|
||||
to be drawing a curve, it is actually the knot vector that determines the actual <em>shape</em> of
|
||||
the curve inside that hull.</p>
|
||||
|
||||
<p>After reading the rest of this section you may want to come back here to try some specific knot vectors,
|
||||
and see if the resulting interpolation landscape makes sense given what you will now think should happen!</p>
|
||||
|
||||
<h2>
|
||||
Running the computation
|
||||
</h2>
|
||||
@@ -265,7 +285,7 @@ var BoundingBox = React.createClass({
|
||||
<p>
|
||||
(A nice bit of behaviour in this code is that we work the interpolation "backwards", starting at <code>i=s</code> at
|
||||
each level of the interpolation, and we stop when <code>i = s - order + level</code>, so we always end up with a
|
||||
value for <code>i</code> such that those <code>v[i-1]</code> don't have an array index that doesn't exist)
|
||||
value for <code>i</code> such that those <code>v[i-1]</code> don't try to use an array index that doesn't exist)
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -273,19 +293,27 @@ var BoundingBox = React.createClass({
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Much like poly-Beziers, B-Splines can be either open, running from the first point to the last point, or closed,
|
||||
Much like poly-Béziers, B-Splines can be either open, running from the first point to the last point, or closed,
|
||||
where the first and last point are <em>the same point</em>. However, because B-Splines are an interpolation of
|
||||
curves, not just point, we can't simply make the first and last point the same, we need to link a few point point:
|
||||
for an order <code>d</code> B-Spline, we need to make the last <code>d</code> point the same as the first <code>d</code> points.
|
||||
And the easiest way to do this is to simply append <code>points.splice(0,d)</code> to <code>points</code>. Done!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Of course if we want to manipulate these kind of curves we need to make sure to mark them as "closed" so that
|
||||
we know the coordinate for <code>points[0]</code> and <code>points[n-k]</code> etc. are the same coordinate,
|
||||
and manipulating one will equally manipulate the other, but programming generally makes this really easy by
|
||||
storing references to coordinates (or other linked values such as coordinate weights, discussed in the NURBS
|
||||
section) rather than separate coordinate objects.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
Manipulating the curve through the knot vector
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
The most important thing to understand when it comes to B-splines is that they work <em>because</em> of the concept
|
||||
The most important thing to understand when it comes to B-Splines is that they work <em>because</em> of the concept
|
||||
of a knot vector. As mentioned above, knots represent "where individual control points start/stop influencing
|
||||
the curve", but we never looked at the <em>values</em> that go in the knot vector. If you look back at the N() and
|
||||
a() functions, you see that interpolations are based on intervals in the knot vector, rather than the actual values
|
||||
@@ -303,7 +331,7 @@ var BoundingBox = React.createClass({
|
||||
<h3>Uniform B-Splines</h3>
|
||||
|
||||
<p>
|
||||
The most straightforward type of B-spline is the uniform spline. In a uniform spline, the knots are distributed
|
||||
The most straightforward type of B-Spline is the uniform spline. In a uniform spline, the knots are distributed
|
||||
uniformly over the entire curve interval. For instance, if we have a knot vector of length twelve, then a uniform
|
||||
knot vector would be [0,1,2,3,...,9,10,11]. Or [4,5,6,...,13,14,15], which defines <em>the same intervals</em>,
|
||||
or even [0,2,3,...,18,20,22], which also defines <em>the same intervals</em>, just scaled by a constant factor,
|
||||
@@ -342,7 +370,7 @@ var BoundingBox = React.createClass({
|
||||
<BSplineGraphic sketch={require('./center-cut-bspline')} controller={(owner, knots) => this.bindKnots(owner, knots, "center-cut-bspline")}/>
|
||||
</div>
|
||||
|
||||
<h3>Open-Uniform B-splines</h3>
|
||||
<h3>Open-Uniform B-Splines</h3>
|
||||
|
||||
<p>
|
||||
By combining knot interval collapsing at the start and end of the curve, with uniform knots in between, we
|
||||
@@ -362,16 +390,16 @@ var BoundingBox = React.createClass({
|
||||
<BSplineGraphic sketch={require('./open-uniform-bspline')} controller={(owner, knots) => this.bindKnots(owner, knots, "open-uniform-bspline")}/>
|
||||
</div>
|
||||
|
||||
<h3>Non-uniform B-splines</h3>
|
||||
<h3>Non-uniform B-Splines</h3>
|
||||
|
||||
<p>This is essentialy the "free form" version of a B-spline, and also the least interesting to look at,
|
||||
<p>This is essentialy the "free form" version of a B-Spline, and also the least interesting to look at,
|
||||
as without any specific reason to pick specific knot intervals, there is nothing particularly interesting
|
||||
going on. There is on constraint to the knot vector, and that is that any value <code>knots[k+1]</code>
|
||||
going on. There is one constraint to the knot vector, and that is that any value <code>knots[k+1]</code>
|
||||
should be equal to, or greater than <code>knots[k]</code>.</p>
|
||||
|
||||
<h2>One last thing: Rational B-splines</h2>
|
||||
<h2>One last thing: Rational B-Splines</h2>
|
||||
|
||||
<p>While it is true that this section on B-splines is running quite long already, there is one more thing
|
||||
<p>While it is true that this section on B-Splines is running quite long already, there is one more thing
|
||||
we need to talk about, and that's "Rational" splines, where the rationality applies to the "ratio", or relative
|
||||
weights, of the control points themselves. By introducing a ratio vector with weights to apply to each
|
||||
control point, we greatly increase our influence over the final curve shape: the more weight a control
|
||||
@@ -389,14 +417,14 @@ var BoundingBox = React.createClass({
|
||||
}} />
|
||||
</div>
|
||||
|
||||
<p>Of course this brings us to the final topic that any text on B-splines must touch on before calling it
|
||||
a day: the NURBS, or Non-Uniform Rational B-Spline (NUBRS is not a plural, the capital S actually just stands
|
||||
<p>Of course this brings us to the final topic that any text on B-Splines must touch on before calling it
|
||||
a day: the NURBS, or Non-Uniform Rational B-Spline (NURBS is not a plural, the capital S actually just stands
|
||||
for "spline", but a lot of people mistakenly treat it as if it is, so now you know better). NURBS are an
|
||||
important type of curve in computer-facilitated design, used a lot in 3D modelling (as NURBS surfaces)
|
||||
as well as in arbitrary-precision 2D design due to the level of control a NURBS curve offers designers.
|
||||
</p>
|
||||
|
||||
<p>While a true non-uniform rational B-spline would be hard to work with, when we talk about NURBS we
|
||||
<p>While a true non-uniform rational B-Spline would be hard to work with, when we talk about NURBS we
|
||||
typically mean the Open-Uniform Rational B-Spline, or OURBS, but that doesn't roll off the tongue nearly
|
||||
as nicely, and so remember that when people talk about NURBS, they typically mean open-uniform, which
|
||||
has the useful property of starting the curve at the first control point, and ending it at the last.</p>
|
||||
|
@@ -1,9 +1,37 @@
|
||||
var colors = [
|
||||
'#C00',
|
||||
'#CC0',
|
||||
'#0C0',
|
||||
'#0CC',
|
||||
'#00C',
|
||||
'#C0C',
|
||||
'#600',
|
||||
'#660',
|
||||
'#060',
|
||||
'#066',
|
||||
'#006',
|
||||
'#606'
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
degree: 3,
|
||||
activeDistance: 9,
|
||||
cache: { N: [] },
|
||||
|
||||
setup() {
|
||||
this.size(600, 300);
|
||||
this.points = [
|
||||
{x:0, y: 0},
|
||||
{x:100, y:-100},
|
||||
{x:200, y: 100},
|
||||
{x:300, y:-100},
|
||||
{x:400, y: 100},
|
||||
{x:500, y: 0}
|
||||
];
|
||||
this.knots = this.formKnots(this.points);
|
||||
if(this.props.controller) {
|
||||
this.props.controller(this, this.knots);
|
||||
}
|
||||
this.draw();
|
||||
},
|
||||
|
||||
@@ -15,75 +43,71 @@ module.exports = {
|
||||
this.line(pad,0,pad,this.height);
|
||||
var y = this.height - pad;
|
||||
this.line(0,y,this.width,y);
|
||||
this.N(3, 3, pad);
|
||||
|
||||
var k = this.degree;
|
||||
var n = this.points.length || 4;
|
||||
|
||||
for (let i=0; i<n+1+k; i++) {
|
||||
this.drawN(i, k, pad, (this.width-pad)/(2*(n+2)), this.height-2*pad);
|
||||
}
|
||||
},
|
||||
|
||||
// based on http://www.ibiblio.org/e-notes/Splines/Bspline.java
|
||||
N(n, k, pad) {
|
||||
var n1 = n+1;
|
||||
var nt = n+k+1;
|
||||
var w2 = this.width/2;
|
||||
var h1 = this.height;
|
||||
var step = 0.1;
|
||||
var ti = [0,1,2,3,4,5,6];
|
||||
var t = ti[0];
|
||||
var N = [[],[],[],[],[],[],[],[]];
|
||||
drawN(i, k, pad, w, h) {
|
||||
this.stroke(colors[i]);
|
||||
let knots = this.knots;
|
||||
this.beginPath();
|
||||
for (let start=i-1, t=start, step=0.1, end=i+k+1; t<end; t+=step) {
|
||||
let x = pad + i*w + t*w;
|
||||
let y = this.height - pad - this.N(i, k, t) * h;
|
||||
this.vertex(x, y);
|
||||
}
|
||||
this.endPath();
|
||||
},
|
||||
|
||||
var i1 = 0;
|
||||
for (var l = 0; l < w2; l++) {
|
||||
while (t >= ti[i1] ) {
|
||||
i1++;
|
||||
}
|
||||
var i = i1-1;
|
||||
for (var s = 0; s < nt; s++) {
|
||||
N[s][l] = 0;
|
||||
}
|
||||
N[i][l] = 1;
|
||||
// basis functions calculation
|
||||
for (var m = 2; m <= k; m++) {
|
||||
var jb = i-m+1;
|
||||
if (jb < 0) {
|
||||
jb = 0;
|
||||
}
|
||||
for (var j = jb; j <= i; j++) {
|
||||
N[j][l] = N[j][l]*(t - ti[j])/(ti[j+m-1] - ti[j]) +
|
||||
N[j+1][l]*(ti[j+m] - t)/(ti[j+m] - ti[j+1]);
|
||||
}
|
||||
}
|
||||
t += step;
|
||||
N(i, k, t) {
|
||||
let t_i = this.knots[i];
|
||||
let t_i1 = this.knots[i+1];
|
||||
let t_ik1 = this.knots[i+k-1];
|
||||
let t_ik = this.knots[i+k];
|
||||
|
||||
if (k===1) {
|
||||
return (t_i <= t && t <= t_i1) ? 1 : 0;
|
||||
}
|
||||
|
||||
var colors = [
|
||||
'#C00',
|
||||
'#CC0',
|
||||
'#0C0',
|
||||
'#0CC',
|
||||
'#00C',
|
||||
'#C0C'
|
||||
];
|
||||
let n1 = t - t_i;
|
||||
let d1 = t_ik1 - t_i;
|
||||
let a1 = d1===0? 0: n1/d1;
|
||||
|
||||
var stw = this.width/8;
|
||||
for (let j = 0; j < n1; j++) {
|
||||
t = ti[0];
|
||||
let to = t;
|
||||
this.stroke(colors[j]);
|
||||
for (let l = 1; l < w2; l++) {
|
||||
t += step;
|
||||
let t1 = t;
|
||||
this.line(
|
||||
pad + stw * to,
|
||||
h1 - (h1 * N[j][l-1]) - pad,
|
||||
pad + stw * t1,
|
||||
h1 - (h1 * N[j][l]) - pad
|
||||
);
|
||||
to = t1;
|
||||
}
|
||||
let n2 = t_ik - t;
|
||||
let d2 = t_ik - t_i1;
|
||||
let a2 = d2===0? 0: n2/d2;
|
||||
|
||||
let N1 = 0;
|
||||
if (a1 !== 0) {
|
||||
let n1v = this.ensureN(i,k-1,t);
|
||||
N1 = n1v === undefined ? this.N(i,k-1,t) : n1v;
|
||||
}
|
||||
|
||||
this.stroke(0);
|
||||
this.fill(0);
|
||||
for(let j=0; j<n+k+1; j++) {
|
||||
this.circle(pad + j*stw, h1 - pad, 3);
|
||||
let N2 = 0;
|
||||
if (a2 !== 0) {
|
||||
let n2v = this.ensureN(i+1,k-1,t);
|
||||
N2 = n2v === undefined ? this.N(i+1,k-1,t) : n2v;
|
||||
}
|
||||
|
||||
this.cacheN(i,k,t, a1 * N1 + a2 * N2);
|
||||
return this.cache.N[i][k][t];
|
||||
},
|
||||
|
||||
ensureN(i,k,t) {
|
||||
if (!this.cache.N) { this.cache.N = []; }
|
||||
let N = this.cache.N;
|
||||
if (!N[i]) { N[i] = []; }
|
||||
if (!N[i][k]) { N[i][k] = []; }
|
||||
return N[i][k][t];
|
||||
},
|
||||
|
||||
cacheN(i,k,t,value) {
|
||||
this.ensureN(i,k,t);
|
||||
this.cache.N[i][k][t] = value;
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user