Function unwilling to calculate results, instead assigns/leaves variables NaN - javascript

I'm not able to make function trajgen() to calculate x and y and after three days put in trying I still can't find the solution. The whole program is over 200 lines so I'll cross my fingers you to find something false in the following 'problematic' function. :)
Take a look...
function trajgen(){
$(".reddot").remove();
x=xo;
y=yo;
$(".reddot").css({"top": y, "left": x});
isin=true;
while(isin==true){
x = xo + v0*Math.cos(angle)*time;
y = yo + v0*Math.sin(angle)*time - 0.5*g*Math.pow(time,2);
alert("x= "+x);
alert("y= "+y);
$("#frames").append('<div class = "reddot" style = "top: '+ y + 'px; left: '+ x +'px;"><img src="red.png" height="10" width="10"></div>');
time+=1;
isin=inchecker();
}
return;
}
function inchecker(){
if(y<Dy||y>Ay||x<Dx||x>Bx){
isin = false;
return isin;
}
isin = true;
return isin;
}
Now, when I alert x and y this thing returns me NaNs (i know what it means), for the both coordinates. Another interesting aspect is that function inchecker doesn't stop the buggy reddot appending after they get out of the div I'm using as a element where to draw my trajectory. Instead of getting parabolic arc I get infinitely vertically clonning/appending red points. All other variables work properly, x, y, xo, yo, speed, time... and so on are globals. Xo and yo I get as (0;0) from where to launch the projectile and I found out that all other variables work well, the only problem is with those x and y which I haven't used anywhere else so far. I assigned them with zeros but by now this doesn't change the unwillingness of my script to calculate x and y. #frames is the div where all those things happen. Please, help me and thanks in advance.

At the line where you compute x and y, either angle, v0, xo, or vo is null or not a number.
run a debugger and step through those lines, and check the values in place.

Related

How to recreate the animation function from the specified graph?

I'm trying to find a math function for animating, but so far without success. There must be some very simple solution for this, but I'm a bit confused. I need to get the value of a function like in the example image
.
[A1,B1] - range of possible argument value
[A,C] - range of function values
D - the value of the argument for which the function shows the minimum value
What type of functions is this? I would be grateful for any hints.
I see is piecewise curve: 2 quadratic + 2 line for example something like this in C++:
float x0,x1,x2,y0,y1,y2; // set these to your curve edge points
float fx(float x) // this returns y for any x
{
if (x<=x0) return y0;
if (x<=x1)
{
float a=(x-x1)/(x1-x0);
return y1+a*a*(y0-y1);
}
if (x<=x2)
{
float a=(x-x1)/(x2-x1);
return y1+a*a*(y2-y1);
}
return y2;
}
And here how it looks like:

Cubic Bezier curve not returning proper Y value, given (t, p0, p1, p2, p3)

My goal is to write an animation in JavaScript that performs an ease-in-out style bezier curve animation
(such as in http://cubic-bezier.com/#.42,0,.58,1)
I came up with the following script to calculate the y value given "x" value (time):
function CalculateBezierPoint(t, p0, p1, p2, p3) {
var y = ((1-t)*(1-t)*(1-t)*p0) + (3*(1-t)*(1-t)*t*p1) + (3*(1-t)*t*t*p2) + (t*t*t*p3);
return y;
}
Using the explicit formula from Wikipedia :
Demo - https://codepen.io/anon/pen/QpRzBg
However, the print statements show the Y value going down before going up, when it should ONLY be going up:
0.42
0.3228427793606603
0.3119941308275725
0.3025864871426283
0.29458762995005683
0.2879653408940873
0.28268740161894895
0.27872159376887096
0.27603569898808256
0.27459749892081287
0.2743747752112911
0.2753353095037466
0.27744688344240837
0.28067727867150566
0.2849942768352678
0.29675920854370297
0.3041427053768346
0.3124839317215477
0.3217506690862967
0.33191069937460593
0.34293180410763435
0.35478176492961133
I did manage to find someone else's code that seems to work, here is the output:
0
0.009480343767040133
0.0246451904411195
0.03199616010201068
0.040680303103589804
0.05080871722437687
0.062492500242891866
0.07584274993765482
0.0909705640871857
0.10798704047000454
0.12700327686463134
0.14813037104958607
0.17147942080338874
0.19716152390455938
0.225287778131618
0.25596928126308455
0.28931713107747903
0.3254424253533215
0.36445626186913194
0.4064697384034303
0.4515939527347367
0.499940002641571
Demo - https://codepen.io/anon/pen/evabrr
Both demos use the same input: p0 = .42, p1 = 0, p2 = .58, p3 = 1
I don't know why my attempt fails, and the code I found works. Did I implement the formula wrong? Did I choose the wrong formula? Something else?
So your mistake is neither passing a single value nor the power function. The mistake is that you are assuming that x = t.
I came up with the following script to calculate the y value given "x" value (time):
If x=t then what you have is an explicit bezier curve, not a parametric bezier curve. Explicit meaning that y is a function of x (i.e. y=f(x)). As opposed to a parametric equation where both x and y are functions of t (i.e. x=f(t) and y=f(t)).
One way to test that this is truly the case, set your x values to [0, 1/3, 2/3, 1]. Evenly spaced x-values ensures that x=t and will give you an explicit bezier curve. You can achieve this on http://cubic-bezier.com by setting the x values in the address bar to 0.333 and 0.666. But as soon as you move the control points to either the left or the right your results will again differ.
To get the same effect it is a bit more involved. You must solve for t at a given x and then calculate y from t. Solving for t is a little complex but can be approximated with the newton-raphson method. This link does a much better job explaining how to implement it: http://greweb.me/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/
Late to the party, but: your comment "I think I'm actually making a big error -- the P are supposed to be point values.. which should have (x,y) and I'm only providing one digit" is correct.
A Bezier curve is a parametric function where both x and y (or x, y, and z in 3D) are functions of t. You're only calculating half of the curve, so you need to modify your CalculateBezierPoint function to return an x/y coordinate, not just a y coordinate:
calculateBezierPoint(t, xvalues, yvalues) {
return new Point(
x = calculateBezierDim(t, x1, x2, x3, x4),
y = calculateBezierDim(t, y1, y2, y3,y4)
);
}
calculateBezierDim(t, vals) {
a=vals[0], b=vals[1], c=vals[2], d=vals[3];
mt = 1-t;
t2 = t*t;
mt2 = mt*mt;
return a * mt*mt2 + 3 * b * mt2 * t + 3 * c * mt * t2 + d * t2 * t;
}
(Adapted to your programming language and data types of course).
Then you can draw that x/y coordinate instead.
step = some small value
S = calculateBezierPoint(0, xvals, yvals)
for(t=step; t<1+step; t+=step) {
E = calculateBezierPoint(t, xvals, yvals)
drawLine(S.x, S.y, E.x, E.y)
S = E
}
I think there could be an error in your formula, with operator precedence. I would try using the exponentiation function where appropriate, would make things easier to debug.
Math.pow(base, exponent)

javascript math formula. find inverse

I have some function:
function calc_degree(a,b,c,cnt) {
if(cnt==0) {
return a;
}
b = b+c;
a = a-b;
return calc_degree(a,b,c,cnt-1);
}
Shortly, it calcs degree of rotation some cicle, which rotation speed increase smoothly. Function returns summary degrees of the rotation. For example:
calc_degree(0,0,1.5,6*1000/time_out);
//a - start angle; b-value of increasing ratoation degree every tick.
//c-increase value; time_out - interval of rotation.
In this example, function returns summary degrees of rotation by 6 seconds.
So, how can I calc the "c" param, if I know the "a" and "cnt"? I need to get the increase value, knowing the summary degrees of rotation and time/tick. If my "a" value is 2790, I need to decrease it every time by "c" value and the last value of "a" must be zero.
Make it a proper recursion, with indices and all:
b[n] = b[n-1] + c => b[n] = b[0] + n*c
a[n] = a[n-1] - b[n] = a[n-1] - b[0] - n*c
results in
a[n] = a[0] - n*b[0] - n*(n+1)/2 * c
This shows you how to get c if a[0]=b[0]=0.
To get a[n]=b[n]=0, you would first need c=-b[0]/n and then c=-a[n]/(n*(n-1)/2). This only works if in the beginning 2*a[0] == (n-1)*b[0].
I cannot comment yet, so I'll add it here. LutzL answer is correct. The problem is that if you add more than one constraint to the problem (in your case requiring both a and b to go to 0) you are reducing the degrees of freedom of the problem. In your case you cannot make a go to zero smoothly (with both a and b 0) if there's not the relation stated by LutzL in the beginning. You can solve it by adding another degree of smoothness (ex: c[n] = c[n-1] + d.) But then you wont be able to make a, b and c tend to 0 without extra constraints.

The correct way to calculate Radians in Javascript?

I have this fiddle http://jsfiddle.net/pp7oby62/. The fiddle consists of a paddle game with rocks being hurdled at a paddle on a 80x10 sensor grid. The function notify_player has two parameters which give me the location of the rocks and the paddle. My code looks like this:
defender.start(
function notify_player(rocks, paddle_y) {
var rocks_x = Math.max(rocks);
var rocks_y = Math.min(rocks);
var paddle_x = Math.max(paddle_y);
var paddle_yp = Math.min(paddle_y);
var deltaY = rocks_y - paddle_yp;
var deltaX = rocks_x - paddle_x;
var angleInRadians = Math.atan2(deltaY, deltaX);
var angleRound=Math.round(angleInRadians);
// random plan
var moves = [];
for (var i = 0; i < 22; i++) {
// -1, 0, 1 to move the fiddle up and down on the grid
//moves.push( Math.floor(Math.random()*3) - 1 );
if (angleInRadians >0) moves.push(-1);
else if (angleInRadians < 0) moves.push(0, 1, -1);
}
return moves;
}
);
The moves array controls the paddle moving up and down. As you can see I am calculating the angle in radians using the the information I get from the two parameters. But when I run it there's no effect on the movement of paddle when I give conditional loops stating that the angle is >0 or <0. But suppose I say:
if(angleInRadians!==0)
The paddle moves.
How could this be possible?
there's no effect on the movement of paddle when I give conditional loops stating that the angle is >0 or <0.
This could simply be when anleInRadians is zero - you've got a blind spot there.
But suppose I say: if(angleInRadians!==0) The paddle moves. How could this be possible?
The variable angleInRadians contains the value NaN. It is neither smaller nor greater than zero, as it's not a number - but it is definitely not zero. Yes, NaNs equality relations are a bit odd (it's not even equal to itself).
The reason why you are getting NaN here is that you're doing invalid mathematical operations. rocks is an array of objects (you really should log and inspect it), which you cannot call Math.min or .max on.
Btw, it doesn't even make sense to call min or max on a single value. And you won't get the paddle_x position by calling Math.max(paddle_y).

How to determine if a collision is new or continued from last frame

I have this function which detects the collision between to objects. It is called within a Ticker (FPS 60). The if statement will run as long as the two objects are together. I think this has something to do with the ticker and it running the if every frame. What would be the best way to fix this so that for example when the two objects collided the person gets one point instead of four or ten.
function collDec(){
var minDistance = 10 + 10;
var xDist = circle.x - arrow.x;
var yDist = circle.y - arrow.y;
var distance = Math.sqrt(xDist*xDist + yDist*yDist);
if (distance < minDistance) {
Lpoints.text = "Points: " + ++pointsAm;
//console.log("HIT");
var dingSound = createjs.Sound.play("sound/ding.mp3");
//reset();
}
} // End of collDec
Have an int on each object, recently collided
If a collision occurs, set both recently collided on both objects to 2
At the start of every frame, decrement recently collided on all objects by 1 to a minimum of 0
If a collision occurs and recently collided is 1 or higher* on both objects, do not add points/play a sound but still increment recently collided.
*I think 'exactly 1' may be fine too. It seems to only matter in 'three balls collide simultaneously or near simultaneously' cases.

Categories