Quadratic function for increment speedup of countup - javascript

I'm writing a jQuery plugin for fast-counting up to a value when a page loads. Since javascript can't run as fast as I want it to for larger numbers, I want to increase the increment step so that it completes within a given timeframe, so I'd need a quadratic function that passes through origo and has it's turning point at y = target counting value and x = target duration, but I can't get a grip on the math for doing this. Since both the number and the duration can change, I need to be able to calculate it in javascript aswell.
Hopefully someone can help me with this one!

Let's formalize the statement a bit.
We seek an equation of the form
y = a*x*x + b*x + c
where x is the time axis and y is a count axis. We know that one point on the curve is (0,0) and another point is (xf, yf) where xf is the final time and yf is the target count. Further, you wish for the derivative of this equation to be zero at (xf, yf).
y' = 2*a*x + b
So I have three equations and three unknowns:
(0,0) => 0 = c
(xf, yf) => yf = a*xf*xf + b*xf + c
y' = 0 # (xf, yf) => 0 = 2*a*xf + b
You should be able to solve it from there.

// Create a quadratic function that passes through origo and has a given extremum.
// x and y are the coordinates for the extremum.
// Returns a function that takes a number and returns a number.
var quadratic = function (x, y) {
var a = - (y / (x * x));
var b = (2 * y) / x;
return function (x) {
return a * x * x + b * x;
};
};

Related

Figuring out the value for PI

Let's say I have a function called bars()
bars () {
const bars = []
for (let i = 0; i < this.numberOfBars; i++) {
bars.push(Math.sqrt(this.numberOfBars * this.numberOfBars - i * i))
}
return bars
}
If I'm reducing the bars array to approximate PI, what should be on the right side of the arrow function?
PI = bars().reduce((a, b) =>
I tried adding the values and dividing by the number of bars, but I'm not getting anywhere near the approximation of Pi. I feel like there's a simple trick that I'm missing.
Your funcion seems to list lengths of "bars" in a quarter of a circle, so we have to add them all up (to have the area of the quarter of a circle), then multiply by 4 (because there is 4 quarter) and the divide by this.numberOfBars ^ 2 because area = π * r^2, but like we have to know the radius, it is better using a pure function :
// Your function rewritten as a pure one
const bars = numberOfBars => {
const bars = []
for (let i = 0; i < numberOfBars; i++) {
bars.push(Math.sqrt(numberOfBars * numberOfBars - i * i))
}
return bars
}
// Here we take 1000 bars as an example but in your case you replace it by this.numberOfBars
// Sum them all up, multiply by 4, divide by the square of the radius
const PI = bars(1000).reduce((g, c) => g + c) * 4 / Math.pow(1000, 2)
console.log(PI)
/** Approximates PI using geometry
* You get a better approximation using more bars and a smaller step size
*/
function approximatePI(numberOfBars, stepSize) {
const radius = numberOfBars * stepSize;
// Generate bars (areas of points on quarter circle)
let bars = [];
// You can think of i as some point along the x-axis
for (let i = 0; i < radius; i += stepSize) {
let height = Math.sqrt(radius*radius - i*i)
bars.push(height * stepSize);
}
// Add up all the areas of the bars
// (This is approximately the area of a quarter circle if stepSize is small enough)
const quarterArea = bars.reduce((a, b) => a + b);
// Calculate PI using area of circle formula
const PI = 4 * quarterArea / (radius*radius)
return PI;
}
console.log(`PI is approximately ${approximatePI(100_000, 0.001)}`);
There is no reason to push all terms to an array, then to reduce the array by addition. Just use an accumulator variable and add all terms to it.
Notice that the computation becomes less and less accurate the closer you get to the end of the radius. If you sum to half of the radius, you obtain r²(3√3+π)/24, from which you can draw π.
(Though in any case, this is one of the worst methods to evaluate π.)

noisy line between two specific points P5.js

I'm trying to draw a noisy line (using perlin noise) between two specific points.
for example A(100, 200) and B(400,600).
The line could be a points series.
Drawing random noisy line is so clear but I dont know how can I calculate distance specific points.
working of P5.js.
I don't have any code written yet to upload.
Please can anyone help me?
I tried to add sufficient comments that you would be able to learn how such a thing is done. There are a number of things that you should make yourself aware of if you aren't already, and it's hard to say which if these you're missing:
for loops
drawing lines using beginShape()/vertex()/endShape()
Trigonometry (in this case sin/cos/atan2) which make it possible to find angles and determine 2d offsets in X and Y components at a given angle
p5.Vector() and its dist() function.
// The level of detail in the line in number of pixels between each point.
const pixelsPerSegment = 10;
const noiseScale = 120;
const noiseFrequency = 0.01;
const noiseSpeed = 0.1;
let start;
let end;
function setup() {
createCanvas(400, 400);
noFill();
start = createVector(10, 10);
end = createVector(380, 380);
}
function draw() {
background(255);
let lineLength = start.dist(end);
// Determine the number of segments, and make sure there is at least one.
let segments = max(1, round(lineLength / pixelsPerSegment));
// Determine the number of points, which is the number of segments + 1
let points = 1 + segments;
// We need to know the angle of the line so that we can determine the x
// and y position for each point along the line, and when we offset based
// on noise we do so perpendicular to the line.
let angle = atan2(end.y - start.y, end.x - start.x);
let xInterval = pixelsPerSegment * cos(angle);
let yInterval = pixelsPerSegment * sin(angle);
beginShape();
// Always start with the start point
vertex(start.x, start.y);
// for each point that is neither the start nor end point
for (let i = 1; i < points - 1; i++) {
// determine the x and y positions along the straight line
let x = start.x + xInterval * i;
let y = start.y + yInterval * i;
// calculate the offset distance using noice
let offset =
// The bigger this number is the greater the range of offsets will be
noiseScale *
(noise(
// The bigger the value of noiseFrequency, the more erretically
// the offset will change from point to point.
i * pixelsPerSegment * noiseFrequency,
// The bigger the value of noiseSpeed, the more quickly the curve
// fluxuations will change over time.
(millis() / 1000) * noiseSpeed
) - 0.5);
// Translate offset into x and y components based on angle - 90°
// (or in this case, PI / 2 radians, which is equivalent)
let xOffset = offset * cos(angle - PI / 2);
let yOffset = offset * sin(angle - PI / 2);
vertex(x + xOffset, y + yOffset);
}
vertex(end.x, end.y);
endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
This code makes jaggy lines, but they could be smoothed using curveVertex(). Also, making the line pass through the start and end points exactly is a little tricky because the very next point may be offset by a large amount. You could fix this by making noiseScale very depending on how far from an endpoint the current point is. This could be done by multiplying noiseScale by sin(i / points.length * PI) for example.

How can I offset a global directional force to be applied over a local axis?

I want to apply a forward force in relation to the object's local axis, but the engine I'm using only allows to me apply a force over the global axis.
I have access to the object's global rotation as a quaternion. I'm not familiar with using quats however (generally untrained in advanced maths). Is that sufficient information to offset the applied force along the desired axis? How?
For example, to move forward globally I would do:
this.entity.rigidbody.applyForce(0, 0, 5);
but to keep that force applied along the object's local axis, I need to distribute the applied force in a different way along the axes, based on the object's rotational quat, for example:
w:0.5785385966300964
x:0
y:-0.815654993057251
z:0
I've researched quaternions trying to figure this out, but watching a video on what they are and why they're used hasn't helped me figure out how to actually work with them to even begin to figure out how to apply the offset needed here.
What I've tried so far was sort of a guess on how to do it, but it's wrong:
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
//converted this from a python func on wikipedia,
//not sure if it's working properly or not
function convertQuatToEuler(w, x, y, z){
ysqr = y * y;
t0 = 2 * (w * x + y * z);
t1 = 1 - 2 * (x * x + ysqr);
X = Math.degrees(Math.atan2(t0, t1));
t2 = 2 * (w * y - z * x);
t2 = (t2 >= 1) ? 1 : t2;
t2 = (t2 < -1) ? -1 : t2;
Y = Math.degrees(Math.asin(t2));
t3 = 2 * (w * z + x * y);
t4 = 1 - 2 * (ysqr + z * z);
Z = Math.degrees(Math.atan2(t3, t4));
console.log('converted', {w, x, y, z}, 'to', {X, Y, Z});
return {X, Y, Z};
}
function applyGlobalShift(x, y, z, quat) {
var euler = convertQuatToEuler(quat.w, quat.x, quat.y, quat.z);
x = x - euler.X; // total guess
y = y - euler.Y; // total guess
z = z - euler.Z; // total guess
console.log('converted', quat, 'to', [x, y, z]);
return [x, y, z];
}
// represents the entity's current local rotation in space
var quat = {
w:0.6310858726501465,
x:0,
y:-0.7757129669189453,
z:0
}
console.log(applyGlobalShift(-5, 0, 0, quat));
Don't laugh at my terrible guess at how to calculate the offset :P I knew it was not even close but I'm really bad at math
Quaternions are used as a replacement for euler angles. Your approach, thus, defeats their purpose. Instead of trying to use euler angles, levy the properties of a quaternion.
A quaternion has 4 components, 3 vector components and a scalar component.
q = x*i + y*j + z*k + w
A quaternion therefore has a vector part x*i + y*j + z*k and a scalar part w. A vector is thus a quaternion with a zero scalar or real component.
It is important to note that a vector multiplied by a quaternion is another vector. This can be easily proved by using the rules of multiplication of quaternion basis elements (left as an exercise for the reader).
The inverse of a quaternion is simply its conjugate divided by its magnitude. The conjugate of a quaternion w + (x*i + y*j + z*k) is simply w - (x*i + y*j + z*k), and its magnitude is sqrt(x*x + y*y + z*z + w*w).
A rotation of a vector is simply the vector obtained by rotating that vector through an angle about an axis. Rotation quaternions represent such an angle-axis rotation as shown here.
A vector v can be rotated about the axis and through the angle represented by a rotation quaternion q by conjugating v by q. In other words,
v' = q * v * inverse(q)
Where v' is the rotated vector and q * v * inverse(q) is the conjugation operation.
Since the quaternion represents a rotation, it can be reasonably assumed that its magnitude is one, making inverse(q) = q* where q* is the conjugate of q.
On separating q into real part s and vector part u and simplifying the quaternion operation (as beautifully shown here),
v' = 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
Where dot returns the dot product of two vectors, and cross returns the cross product of two vectors.
Putting the above into (pseudo)code,
function rotate(v: vector3, q: quaternion4) -> vector3 {
u = vector3(q.x, q.y, q.z)
s = q.w
return 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
}
Now that we know how to rotate a vector with a quaternion, we can use the world (global) rotation quaternion to find the corresponding world direction (or axis) for a local direction by conjugating the local direction by the rotation quaternion.
The local forward axis is always given by 0*i + 0*j + 1*k. Therefore, to find the world forward axis for an object, you must conjugate the vector (0, 0, 1) with the world rotation quaternion.
Using the function defined above, the forward axis becomes
forward = rotate(vector3(0, 0, 1), rotationQuaternion)
Now that you have the world forward axis, a force applied along it will simply be a scalar multiple of the world forward axis.

Calculate minimum value not between set of ranges

Given an array of circles (x,y,r values), I want to place a new point, such that it has a fixed/known Y-coordinate (shown as the horizontal line), and is as close as possible to the center BUT not within any of the existing circles. In the example images, the point in red would be the result.
Circles have a known radius and Y-axis attribute, so easy to calculate the points where they intersect the horizontal line at the known Y value. Efficiency is important, I don't want to have to try a bunch of X coords and test them all against each item in the circles array. Is there a way to work out this optimal X coordinate mathematically? Any help greatly appreciated. By the way, I'm writing it in javascript using the Raphael.js library (because its the only one that supports IE8) - but this is more of a logic problem so the language doesn't really matter.
I'd approach your problem as follows:
Initialize a set of intervals S, sorted by the X coordinate of the interval, to the empty set
For each circle c, calculate the interval of intersection Ic of c with with the X axis. If c does not intersect, go on to the next circle. Otherwise, test whether Ic overlaps with any interval(s) in S (this is quick because S is sorted); if so, remove all intersecting intervals from S, collapse Ic and all removed intervals into a new interval I'c and add I'c to S. If there are no intersections, add Ic to S.
Check whether any interval in S includes the center (again, fast because S is sorted). If so, select the interval endpoint closest to the center; if not, select the center as the closest point.
Basically the equation of a circle is (x - cx)2 + (y - cy)2 = r2. Therefore you can easily find the intersection points between the circle and X axis by substituting y with 0. After that you just have a simple quadratic equation to solve: x2 - 2cxx + cx2 + cy2 - r2 = 0 . For it you have 3 possible outcomes:
No intersection - the determinant will be irrational number (NaN in JavaScript), ignore this result;
One intersection - both solutions match, use [value, value];
Two intersections - both solutions are different, use [value1, value2].
Sort the newly calculated intersection intervals, than try merge them where it is possible. However take in mind that in every program language there approximation, therefore you need to define delta value for your dot approximation and take it into consideration when merging the intervals.
When the intervals are merged you can generate your x coordinates by subtracting/adding the same delta value to the beginning/end of every interval. And lastly from all points, the one closest to zero is your answer.
Here is an example with O(n log n) complexity that is oriented rather towards readability. I've used 1*10-10 for delta :
var circles = [
{x:0, y:0, r:1},
{x:2.5, y:0, r:1},
{x:-1, y:0.5, r:1},
{x:2, y:-0.5, r:1},
{x:-2, y:0, r:1},
{x:10, y:10, r:1}
];
console.log(getClosestPoint(circles, 1e-10));
function getClosestPoint(circles, delta)
{
var intervals = [],
len = circles.length,
i, result;
for (i = 0; i < len; i++)
{
result = getXIntersection(circles[i])
if (result)
{
intervals.push(result);
}
}
intervals = intervals.sort(function(a, b){
return a.from - b.from;
});
if (intervals.length <= 0) return 0;
intervals = mergeIntervals(intervals, delta);
var points = getClosestPoints(intervals, delta);
points = points.sort(function(a, b){
return Math.abs(a) - Math.abs(b);
});
return points[0];
}
function getXIntersection(circle)
{
var d = Math.sqrt(circle.r * circle.r - circle.y * circle.y);
return isNaN(d) ? null : {from: circle.x - d, to: circle.x + d};
}
function mergeIntervals(intervals, delta)
{
var curr = intervals[0],
result = [],
len = intervals.length, i;
for (i = 1 ; i < len ; i++)
{
if (intervals[i].from <= curr.to + delta)
{
curr.to = Math.max(curr.to, intervals[i].to);
} else {
result.push(curr);
curr = intervals[i];
}
}
result.push(curr);
return result;
}
function getClosestPoints(intervals, delta)
{
var result = [],
len = intervals.length, i;
for (i = 0 ; i < len ; i++)
{
result.push( intervals[i].from - delta );
result.push( intervals[i].to + delta );
}
return result;
}
create the intersect_segments array (normalizing at x=0 y=0)
sort intersectsegments by upperlimit and remove those with upperlimit<0
initialize point1 = 0 and segment = 0
loop while point1 is inside intersectsegment[segment]
4.1. increment point1 by uppper limit of intersectsegment[segment]
4.2. increment segment
sort intersectsegments by lowerlimit and remove those with loerlimit>0
initialize point2 = 0 and segment = 0
loop while point2 is inside intersectsegments[segment]
7.1. decrement point2 by lower limit of segment
7.2. decrement segment
the point is minimum absolute value of p1 and p2

Efficient algorithm for equation

I want to ask about efficient algorithm.
Example i have equation :
x = y + z;
if the value of variable y = 1, variable z = 2 so variable x is 3
But how to get value of y automatically if variable x = 3 and variable z = 2 with that equation? without create new equation y = x - z
I hope can get sample code using C# or javascript.
Another example, if the equation is
a = (((x + y - z)/2)*10)^4
The equation is from program, user submit value of 3 varibles.
User submit variable (x, y, z) or (y, z, a) or (z, a, x) or (a, x, y)
if user input value for var x, y and z, program can displaying value of a with that equation. Without create a = ...
if user input value for var y, z and a, program can displaying value of x with that equation. Without create x = ...
if user input value for var z, a and x, program can displaying value of y with that equation. Without create y = ...
if user input value for var a, x and y, program can displaying value of z with that equation. Without create z = ...
What you are looking for is an 'equation solver'. This is non-trivial and there is quite a bit of research on this and some well-known large mathematical software do this.
For more details, please google 'Algorithms for Computer Algebra'.
You have to resolve the equations with respect to the unknown variable:
x = y + z;
is equivalent to
y = x - z;
and
z = x - y;
For the second equation it is more difficult. If a < 0 there will be no solution. Otherwise you can first take the 4th root:
a = (((x + y - z)/2)*10)^4 <=> sqrt(sqrt(a)) = +/- (x + y + z) * 5
Then resolve it with respect to x, y or z. Note that you will get two solutions in general.
There are programs and libraries that can do these calculations automatically: Check for "symbolic math" or "computer algebra systems".
i sense a deep research of math on that problem you present, you can serach on google about equation algorithm solve that a link of wikipedia
Yes in case you have a simple workflow of some basic algorithm to find a variable
let us suppose this environment;
since there are always going to be three variables, you can valid that only one of the three is null and then select the equation of the variable you want to find if non are null then you send a message that no value are null
The original equation is x=y+z-a
x=5; y=7; z=2; a=null;
If (!x.hasValue ()){
x= y + z - a;
}
....
Else if (!a.hasValue ()){
a = -(x + y + a);
}Else{Console.Write("Don't give value to all variable");}
This isn't how it works. In programming languages you don't really have equations but rather assignments. You can assign a right-side value to the variable on the left side.
So the only way to obtain y, when having x and z is by running
y = x - z
EDIT: you may want to create something like
myFunction(double? x=null, double? y=null, double? z=null, double? a=null)
And then inside you check which variable is null (so not used), and perform your calculations accordingly. You would run it like this
var something = myFunction(x: 1, y: 2, a: 3)
If you don't want to write a new line of code and get the result of 'y' when 'x' is diferent to zero within the same equation, try this ...
// equation : x = y + z
var x=3,y=0,z=2;
x = ((x!=0) ? (x-z) : y ) + z;
console.log("Result : "+ x);
// or saving the value in 'y'
x = ((x!=0) ? y = (x-z) : y ) + z;
console.log("Result 2 : "+ x);
Answering the first question:
Y = X - Z
is the only possible solution. There aren't other ways to calculate Y.
This because computers can't solve equations (or better, they can be programmed to solve them, but only using 'Y = X - Z') , they can change the value of a variable. In this case we set the Y value to (X - Z) value.
Answering the second question:
You can solve that equation doing
X = fourth square of (...)
or you can use libraries that do all this work by themselves, like 'computer algebra system' (Also cited by #FrankPuffer)
Definitely: you can solve the equations doing inverse operation, like 'Y = X - Z', or by using libraries that simplify writing code.

Categories