Curve Programmatically Calculated? - performance

How can I calculate y in this curve ? t is the variable. Origin is (0|0) of course.
the tangents at t=0, t=0,5 and t=1 must be perfectly horizontal (incline = 0)
only basic mathematical operators are available (Java / Actionscript 3)
I have to calculate this a few hundred times each frame in Actionscript 3. So calculation needs good performance. Right now I'm actually failing at correctness of calculation (I'm not a mathematician).

Not sure about performance, but
-0.5 * cos(x * 2pi) + 0.5
AS3:
y = -0.5 * Math.cos(x * 2 * Math.PI) + 0.5;
seems to be the curve you are looking for.
You can view or edit the curve here:
wolfram alfa curve

The function suggested by bjornson (-0.5*cos(x) + 0.5) looks good.
One idea to improve performance is that you at the start of your application create a table of the values of that function at different times.
If you use fix timesteps, then the table is all you'll need. If you have variable time steps, then you can just do linear interpolation between the two closest times to the time you're calculating.

y(t) = 16 * t * t * (t - 1) * (t - 1)
I reckon that one satisfies your requirements

I tried my own way and I came up with a polynomial:
y = 16 * (t - 0.5)^4 - 8 * (t - 0.5)^2 + 1
y = 16 * Math.pow((t - 0.5), 4) - 8 * Math.pow((t - 0.5), 2) + 1;
// forgot to shift the curve 0.5 to the right, corrected

Related

Flocking/ Boids Algorithm : Field Of view specified by angle in 3D

I am trying to make boids algorithm in Unity 3D.
I got into one problem: How to implement field of view in specific angle?
360 degrees is easy - U check only distance between two boids. But I dont want boids able to look behind themself. I also want to be able to change angle of view in Inspector, so it must be based on calculations.
I would be gratefull for any ideas:(
I already tried with mesh collider which is cone but it didnt go well. - not working for 180 and higher. So I am looking best way to calculate this.
Assume that the boid is at point p = (p.x, p.y, p.z) heading toward some point h = (h.x, h.y, h.z), and we want to know whether an object at point q = (q.x, q.y, q.z) is in the boid's field of vision.
The Law of Cosines gives us a formula for the cosine of the angle φ between the boid's heading and the boid's path to the object:
(h−p) · (q−p)
cos(φ) = ---------------
||h−p|| ||q−p||
= (dx1*dx2 + dy1*dy2 + dz1*dz2) /
(sqrt(dx1*dx1 + dy1*dy1 + dz1*dz1) * sqrt(dx2*dx2 + dy2*dy2 + dz2*dz2))
where
dx1 = h.x - p.x
dy1 = h.y - p.y
dz1 = h.z - p.z
dx2 = q.x - p.x
dy2 = q.y - p.y
dz2 = q.z - p.z
Given some angle ρ (in whatever units your cosine function accepts, usually radians) past which the boid cannot see (putting the field of vision at 2ρ), we have
φ > ρ if and only if cos(φ) < cos(ρ),
so we can precompute cos(ρ) and then use the above formula for repeated tests.
To avoid division by zero and other numerical problems, you might want to check whether the denominator of the division is very small and if so declare that the boid can feel whatever the object is even outside its field of vision.

Bezier curve: I want to implement an algorithm to draw a continuous curve with bezier algorithm

Through the internet I found the quadratic beizer curve by given three control points. But what should I do if I have a set of points?
x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t *
p[2].y;
In my program, I will have a touch event, when user touches it and move the finger around the screen, the program starts to draw curve.
If I am doing Android I can use quadTo but I can't do it that way coz I want to do it in many platform
For this you will need to use a curve fitting algorithm, this is typcally done iteratively using a least square solution.
A common reference for this is graphics-gems FitCurve.c, see:
https://github.com/erich666/GraphicsGems/blob/master/gems/FitCurves.c
While this is a good reference its not so usable as a library function since its using static vars everywhere.
I've extracted open-toonz curve fitting (also based on FitCurve.c) into a stand-alone, single file C library - which can calculate the curve.
https://developer.blender.org/diffusion/B/browse/master/extern/curve_fit_nd/intern/curve_fit_cubic.c (has various improvements, see header for details)

Equation for time-versus-position graph for iOS 7 spring animation (animateWithDuration:delay:usingSpringWithDamping:...)

Given the spring parameters used in [UIView animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:]:
usingSpringWithDamping
initialSpringVelocity
what is the mathematical equation for the time-versus-position graph?
(I'm trying to get a handle on the new spring animation API in iOS 7, but I'm not getting good results, and experimentation is taking too long. My goal is to get as close as possible to some animation curve that I would have specified using CAMediaTimingFunction if I were to use Core Animation instead of UIView's block-object animation.)
DampingRatio
The damping ratio for the spring animation as it approaches its quiescent state.
To smoothly decelerate the animation without oscillation, use a value of 1. Employ a damping ratio closer to zero to increase oscillation.
As the damping value approaches 0.0 the spring becomes more bouncy.
Velocity
The initial spring velocity. For smooth start to the animation, match this value to the view’s velocity as it was prior to attachment.
A value of 1.0 for an initial spring velocity corresponds to the total animation distance traversed in one second. For example, if the total animation distance is 200 points and you want the start of the animation to match a view velocity of 100 pt/s, use a value of 0.5.
Example:
[UIView animateWithDuration:2.0
delay:0.0
usingSpringWithDamping:0.4
initialSpringVelocity:0.5
options:(UIViewAnimationOptions)options
animations:^{
}
completion:nil];
I believe the resulting mathematical equation is the one described here: http://en.wikipedia.org/wiki/Damping
The damping argument corresponds to damping ratio ζ, and ζ = 1 results in so-called critically damped spring that converges to final position as fast as possible without oscillating.
With zero initial velocity it corresponds to something like the ease-in-ease-out curve, but with more steep ease-in part and smoother ease-out part.
For damping ratio greater than one the animation will look more linear.
For damping ratio less than one oscillation around the final position will appear. Its frequency can be derived from animation duration and probably other arguments.
Here is what the docs say about the initial velocity, which should be pretty clear:
The initial spring velocity. For smooth start to the animation, match this value to the view’s velocity as it was prior to attachment.
A value of 1 corresponds to the total animation distance traversed in one second. For example, if the total animation distance is 200 points and you want the start of the animation to match a view velocity of 100 pt/s, use a value of 0.5.
There are mainly four kinds of spring APIs in iOS:
SwiftUI Animation.spring(response:dampingFraction:blendDuration:)
SwiftUI Animation.interpolatingSpring(mass:stiffness:damping:initialVelocity:)
UIView.animate(withDuration: delay: usingSpringWithDamping: initialSpringVelocity: options: animations: completion:)
CASpringAnimation (with 4 physical properties: mass, stiffness, damping, initialVelocity)
They are based on the same physical process thus have the same base equation, which can be written as
func curveFunc(_ t: Double) -> Double {
let v0 = initialVelocity
let zeta = dampingRatio
let y: Double
if abs(zeta - 1.0) < 1e-8 {
let c1 = -1.0
let c2 = v0 - omega
y = (c1 + c2 * t) * exp(-omega * t)
} else if zeta > 1 {
let s1 = omega * (-zeta + sqrt(zeta * zeta - 1))
let s2 = omega * (-zeta - sqrt(zeta * zeta - 1))
let c1 = (-s2 - v0) / (s2 - s1)
let c2 = (s1 + v0) / (s2 - s1)
y = c1 * exp(s1 * t) + c2 * exp(s2 * t)
} else {
let a = -omega * zeta
let b = omega * sqrt(1 - zeta * zeta)
let c2 = (v0 + a) / b
let theta = atan(c2)
// Alternatively y = (-cos(b * t) + c2 * sin(b * t)) * exp(a * t)
y = sqrt(1 + c2 * c2) * exp(a * t) * cos(b * t + theta + Double.pi)
}
return y + 1
}
There are three parameters: initialVelocity, dampingRatio and omega. dampingRatio determines the shape of the curve, when dampingRatio is 0 it is undamped harmonic oscillator, larger dampingRatio means larger friction. Using SwiftUI Animation.spring, you can have a dampingRatio that is greater than 1, using the other three APIs you can't. omega is the angular frequency if there is no damping, larger omega means quicker oscillation.
t is time in seconds. The return value of this function is relative: 0 means the starting point of the animation and 1 means the end point of the animation. initialVelocity is also relative. A value of 1 corresponds to the total animation distance traversed in one second.
Four different APIs have different ways to determine the three parameters.
(1) In Animation.spring API,
omega = 2 * π / response,
initialVelocity = 0,
dampingRatio is just dampingFraction.
(2) In Animation.interpolatingSpring API,
omega = sqrt(stiffness / mass),
dampingRatio = min(1.0, damping / 2 / sqrt(stiffness * mass))
(3) In UIView.animate API, dampingRatio and initialVelocity is just in the API's parameter, but dampingRatio is not allowed to be greater than 1. omega is calculated from the duration parameter. If dampingRatio == 1, omega is the value such that
abs(-1 + (v0 - omega) * duration) * exp(-omega * duration) == 0.001.
If dampingRatio < 1, omega is the value such that
abs(c2) * exp(a * t) == 0.001,
where c2 and a are defined in curveFunc shown above.
(4) CASpringAnimation is the same as (2).
I've written a project github.com/CosynPa/RevealSpringAnimation to mimic system spring animations. Check it out if you'd like to see more details.

Calculating average of two values, minimizing errors

I am doing some floating point calculations and the results are not as accurate as I want them to be.
This is the algorithm:
...
center = (max_x + min_x) / 2
distance = old_x - center
new_x = center + (distance * factor)
return new_x
min_x, max_x, and old_x are all floats.
I believe that the greatest error is introduced when I'm taking the average of the max and the min, and then the error is multiplied by the factor (which can be a float).
How can I minimize the error due to FP computation so that new_x is as precise as it can be?
If old_x and center are close then you're losing precision.
It's called Loss of significance
You could change the calculation so the subtraction happenS in the end:
center = (max_x + min_x) / 2
new_x = (center + (old_x * factor)) - (center * factor)
Depending on your language, there is probably a fixed/arbitrary precision numeric type you can use such as decimal in python or BigDecimal in Java.
This eliminates at least one source of error from your original algorithm:
# Adding min and max can produce a value of larger magnitude, losing some low-order bits
center = min_x + (max_x - min_x)/2
distance = old_x - center
new_x = center + (distance * factor)
return new_x
If you have more knowledge of the relationship between old_x, min_x andmax_x, you can probably do better than this.
As Yochai says, your problem is probably caused by the subtraction old_x - center. If old_x and center are close to each other then you lose precision.
The simple solution would be do to the computation using double instead of float, but I guess that's not possible. In that case, you need to get rid of the subtraction. One possibility is
distance_max = max_x - center
distance_min = min_x - center
distance = (distance_max + distance_min) / 2
new_x = center + factor * distance
This helps if max_x, min_x and center are quite far apart while the average of max_x and min_x is close to center. If that does not help, perhaps you can adapt the computation of max_x so that you actually compute max_x - center but that needs changes in the part you did not show us.
All the previous implementations do not use rounding and thus have a large error:
Here's how to do this in fixed point math:
I'm using X.1u prevision (1 LSB is used for fraction part).
//center = (max_x + min_x) / 2
center = max_x + min_x // zero error here
// distance = old_x - center
distance = (old_x << 1) - center // zero error here
//new_x = center + (distance * factor)
new_x = (**1** + center + (distance * factor)) >> 1
return new_x
If factor is a fixed point (integer) too with N bits describing the fraction then new_x can be calculated as:
new_x = ( (1 << N) + (center << N) + (distance * factor) ) >> (N + 1)
(center << N) has N+1 fraction bits
distance * factor has N+1 fraction bits
(1 << N) is a 'half' as 1 << (N+1) is 'one' in the above fixed point precision.
After understanding each part, the above line can be compacted:
new_x = ( ((1 + center) << N) + (distance * factor) ) >> (N + 1)
The used integer type should be large enough, off course. If the valid range is unknown, one should check the input to this function and something else. In most cases this isn't needed.
This is as good as it get in fixed point math. This is how HW circuits perform integer math operations.

Draw a point a set distance away from a base point

I'm trying to figure out an algorithm for finding a random point a set distance away from a base point. So for example:
This could just be basic maths and my brain not working yet (forgive me, haven't had my coffee yet :) ), but I've been trying to work this out on paper and I'm not getting anywhere.
coordinate of point on circle with radius R and center (xc, yc):
x = xc + R*cos(a);
y = yc + R*sin(a);
changing value of angle a from 0 to 2*PI you can find any point on circumference.
Use the angle from the verticle as your random input.
Pseudocode:
angle = rand(0,1)
x = cos(angle * 2 * pi) * Radius + x_centre
y = sin(angle * 2 * pi) * Radius + y_centre
Basic Pythagoras.
Pick random number between 0 and 50 and solve h^2 = a^2 + b^2
Add a few random descisions on direction.

Resources