how to control the speed of animation, using a Bezier curve? - math

I found formula only for vector coordinates of cubic curve who help in depicts(build vector image).
Here it is:
B(t) = (1-t)^3*P0 + 3*t*(1-t)^2*P1 + 3*t^2*(1-t)*P2 + t^3*P3
See more at: http://www.ams.org/samplings/feature-column/fcarc-bezier#sthash.85XhcT7H.dpuf
This formula returns the coordinates of the vector, but I can not understand how they can influence the speed of the animation, as in http://cubic-bezier.com/#.17,.67,.83,.67.
Please, direct me to the right way so that I could understand.

bezier curve is a mapping from linear space (usually on interval <0,1>) to nonlinear space. This means you can use it for shape distortion of any signal/value. In your case is not affected time but speed (first derivation of position)
How to do it:
There are many approaches I think that one is done:
If control points of bezier are evenly distributed along the path then the movement is linear. When they are more dense there is the speed slower and vice versa. If you need more complicated movement add more points/bezier patches.
Another option is make the movement linear but not the time
x(t) = x0 + (x1-x0)*t/t_duration;
x(t) is animated item position
t is animation time <0,t_duration>
t_duration is time needed to get to edge position
x0,x1 are start/end positions
now if you increment the time in timer linearly then movement is linear if you do this instead:
u=Bezier(t/t_duration)*t_duration;
and use u instead of t then you achieve the same ... To be clear inside Bezier is time converted to range <0,1> and after back to <0,t_duration>
[notes]
The second option (discrete nonlinear time) brings a whole world of new math problems.
But I use it a lot in advanced motion control and planing. You can achieve nasty things in there that are almost impossible in standard time space with very small complexity instead. But the draw back is that the simple things in classical time space are very hard to do there.

Related

How to smooth hand drawn lines?

So I am using Kinect with Unity.
With the Kinect, we detect a hand gesture and when it is active we draw a line on the screen that follows where ever the hand is going. Every update the location is stored as the newest (and last) point in a line. However the lines can often look very choppy.
Here is a general picture that shows what I want to achieve:
With the red being the original line, and the purple being the new smoothed line. If the user suddenly stops and turns direction, we think we want it to not exactly do that but instead have a rapid turn or a loop.
My current solution is using Cubic Bezier, and only using points that are X distance away from each other (with Y points being placed between the two points using Cubic Bezier). However there are two problems with this, amongst others:
1) It often doesn't preserve the curves to the distance outwards the user drew them, for example if the user suddenly stop a line and reverse the direction there is a pretty good chance the line won't extend to point where the user reversed the direction.
2) There is also a chance that the selected "good" point is actually a "bad" random jump point.
So I've thought about other solutions. One including limiting the max angle between points (with 0 degrees being a straight line). However if the point has an angle beyond the limit the math behind lowering the angle while still following the drawn line as best possible seems complicated. But maybe it's not. Either way I'm not sure what to do and looking for help.
Keep in mind this needs to be done in real time as the user is drawing the line.
You can try the Ramer-Douglas-Peucker algorithm to simplify your curve:
https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
It's a simple algorithm, and parameterization is reasonably intuitive. You may use it as a preprocessing step or maybe after one or more other algorithms. In any case it's a good algorithm to have in your toolbox.
Using angles to reject "jump" points may be tricky, as you've seen. One option is to compare the total length of N line segments to the straight-line distance between the extreme end points of that chain of N line segments. You can threshold the ratio of (totalLength/straightLineLength) to identify line segments to be rejected. This would be a quick calculation, and it's easy to understand.
If you want to take line segment lengths and segment-to-segment angles into consideration, you could treat the line segments as vectors and compute the cross product. If you imagine the two vectors as defining a parallelogram, and if knowing the area of the parallegram would be a method to accept/reject a point, then the cross product is another simple and quick calculation.
https://www.math.ucdavis.edu/~daddel/linear_algebra_appl/Applications/Determinant/Determinant/node4.html
If you only have a few dozen points, you could randomly eliminate one point at a time, generate your spline fits, and then calculate the point-to-spline distances for all the original points. Given all those point-to-spline distances you can generate a metric (e.g. mean distance) that you'd like to minimize: the best fit would result from eliminating points (Pn, Pn+k, ...) resulting in a spline fit quality S. This technique wouldn't scale well with more points, but it might be worth a try if you break each chain of line segments into groups of maybe half a dozen segments each.
Although it's overkill for this problem, I'll mention that Euler curves can be good fits to "natural" curves. What's nice about Euler curves is that you can generate an Euler curve fit by two points in space and the tangents at those two points in space. The code gets hairy, but Euler curves (a.k.a. aesthetic curves, if I remember correctly) can generate better and/or more useful fits to natural curves than Bezier nth degree splines.
https://en.wikipedia.org/wiki/Euler_spiral

Finding time bound path to point in 2D space

I am trying to do flight planning in 3D space, but I actually want to figure out doing it in 2D space first. I have:
an object with a known current position and known current velocity vector
a desired point in space
a desired velocity vector
a desired time
I want to plan a route for the object to take to reach the desired point at the desired time travelling at the desired vector, and taking into account the objects starting vector.
I'm at a bit of a loss on how to achieve this. Any help appreciated.
As noted by eigenchris in a comment, this problem has many possible solutions, so I will propose a method that gives sensible results and allows for flexible customization, depending on the desired properties of your path.
It's easier to split the problem into two parts, first find a path in 2D and then compute the distance along it and solve the problem of matching the velocity and acceleration to the distance as a 1D (plus time) problem.
For the path, Cubic Bézier curves seem ideally suited to the problem. A cubic Bézier curve is defined by 4 control points P0, P1, P2 and P3.
P0 and P3 are the start and end points of the curve. P1 and P2 are control points that are used for specifying the tangent of the curve at the start and end points (defined by the lines P0-P1 and P2-P3 respectively). If you fly along the curve, those are the directions you are moving at the start and end points.
Here is an interactive demo to get a feel for how the positioning of the control points influences the curve (the cubic Bézier is the blue curve on the right with 4 control points).
To define a flight path using a Bézier curve:
Set P0 to the start point of your flight path
Set P3 to the end point
Set P1 to a point in the direction of the starting velocity vector from P0
Set P2 to a point in the opposite direction to the ending velocity vector from P3
Note that the distances from P0 to P1 and from P2 to P3 do not represent the magnitude of the starting and ending velocities. Rather, they specify the tightness of the turn at the start and end of the curve to align the curve with the start and end tangents. Pull the control points in close for a tight turn, push them further out for a wider turn. However if you want to you can make the turn wider the larger the desired velocity vector is, to be more physically realistic.
If you don't want to be turning the whole time, you can segment the path into several Bézier curves, or a Bézier curve then a straight line then a Bézier curve, and make the tangents match up where the different segments meet. For example you might want to take a curved path at the start of the flight path, then follow a straight line for most of the way, the follow a curved path at the end to line up with the desired final direction vector. This gives you total control over your flight path.
The solution generalizes easily to 3 dimensions.
Now that you have a path, you need to figure out how to accelerate and decelerate along the curve to arrive at the destination at the right time and the right speed. First, calculate the distance along the curve:
Arc Length of Bézier Curves
If you know the start time, the end time and the start and end speeds (magnitude of start and end velocity vectors), you can work out how far along the curve you would have flown between the start and end times, assuming you linearly accelerate from the starting speed to the ending speed over the course of the journey (distance is the area under the line):
Since this area will most likely be different to the computed distance along the Bézier Curve, you need to create a segmented function that has the desired area under the line between the start and end times. The image shows two such functions to handle the cases where the distance traveled is greater than desired, and the area is decreased by slowing down then travelling at constant speed then speeding up, and vice versa. The examples show instantaneous changes in acceleration, but not in speed. You can choose any function you like as long as the start and end speeds at the start and end times match the desired values and the area under the function is equal to the distance along the path.

Parallel Offset for Points (Curve/Slope)

I have an Array of Points (CGPoints) which form a curve, actually not a real curve but short line-segments. I need a parallel offset of that curve. Just moving the curve down obviously results in thinner segments if the slope is steep. Any ideas on how i could approach this?
You will need to compute the tangent/normal per segment and then translate the points along the normal.
For a polyline - the normal at a vertex is some combination ((n1 + n2) / 2?) of the two segment normals it straddles, so you may need to take that into account during your "offset" curve computation.
Actually - all you need is the Normal - as indicated here.
Hope this helps.

Simple Problem - Velocity and Collisions

Okay I'm working on a Space sim and as most space sims I need to work out where the opponents ship will be (the 3d position) when my bullet reaches it. How do I calculate this from the velocity that bullets travel at and the velocity of the opponents ship?
Calculate the relative velocity vector between him and yourself: this could be considered his movement if you were standing still. Calculate his relative distance vector. Now you know that he is already D away and is moving V each time unit. You have V' to calculate, and you know it's length but not it's direction.
Now you are constructing a triangle with these two constraints, his V and your bullet's V'. In two dimensions it'd look like:
Dx+Vx*t = V'x*t
Dy+Vy*t = V'y*t
V'x^2 + V'y^2 = C^2
Which simplifies to:
(Dx/t+Vx)^2 + (Dy/t+Vx)^2 = C^2
And you can use the quadratic formula to solve that. You can apply this technique in three dimensions similarly. There are other ways to solve this, but this is just simple algebra instead of vector calculus.
Collision Detection by Kurt Miller
http://www.gamespp.com/algorithms/collisionDetection.html
Add the negative velocity of the ship to the bullet, so that only the bullet moves. Then calculate the intersection of the ship's shape and the line along which the bullet travels (*pos --> pos + vel * dt*).
The question probably shouldn't be "where the ship will be when the bullet hits it," but IF the bullet hits it. Assuming linear trajectory and constant velocity, calculate the intersection of the two vectors, one representing the projectile path and another representing that of the ship. You can then determine the time that each object (ship and bullet) reach that point by dividing the distance from the original position to the intersection position by the velocity of each. If the times match, you have a collision and the location at which it occurs.
If you need more precise collision detection, you can use something like a simple BSP tree which will give you not only a fast way to determine collisions, but what surface the collision occurred on and, if handled correctly, the exact 3d location of the collision. However, it can be challenging to maintain such a tree in a dynamic environment.

Point Sequence Interpolation

Given an arbitrary sequence of points in space, how would you produce a smooth continuous interpolation between them?
2D and 3D solutions are welcome. Solutions that produce a list of points at arbitrary granularity and solutions that produce control points for bezier curves are also appreciated.
Also, it would be cool to see an iterative solution that could approximate early sections of the curve as it received the points, so you could draw with it.
The Catmull-Rom spline is guaranteed to pass through all the control points. I find this to be handier than trying to adjust intermediate control points for other types of splines.
This PDF by Christopher Twigg has a nice brief introduction to the mathematics of the spline. The best summary sentence is:
Catmull-Rom splines have C1
continuity, local control, and
interpolation, but do not lie within
the convex hull of their control
points.
Said another way, if the points indicate a sharp bend to the right, the spline will bank left before turning to the right (there's an example picture in that document). The tightness of those turns in controllable, in this case using his tau parameter in the example matrix.
Here is another example with some downloadable DirectX code.
One way is Lagrange polynominal, which is a method for producing a polynominal which will go through all given data points.
During my first year at university, I wrote a little tool to do this in 2D, and you can find it on this page, it is called Lagrange solver. Wikipedia's page also has a sample implementation.
How it works is thus: you have a n-order polynominal, p(x), where n is the number of points you have. It has the form a_n x^n + a_(n-1) x^(n-1) + ...+ a_0, where _ is subscript, ^ is power. You then turn this into a set of simultaneous equations:
p(x_1) = y_1
p(x_2) = y_2
...
p(x_n) = y_n
You convert the above into a augmented matrix, and solve for the coefficients a_0 ... a_n. Then you have a polynomial which goes through all the points, and you can now interpolate between the points.
Note however, this may not suit your purpose as it offers no way to adjust the curvature etc - you are stuck with a single solution that can not be changed.
You should take a look at B-splines. Their advantage over Bezier curves is that each part is only dependent on local points. So moving a point has no effect on parts of the curve that are far away, where "far away" is determined by a parameter of the spline.
The problem with the Langrange polynomial is that adding a point can have extreme effects on seemingly arbitrary parts of the curve; there's no "localness" like described above.
Have you looked at the Unix spline command? Can that be coerced into doing what you want?
There are several algorithms for interpolating (and exrapolating) between an aribtrary (but final) set of points. You should check out numerical recipes, they also include C++ implementations of those algorithms.
Unfortunately the Lagrange or other forms of polynomial interpolation will not work on an arbitrary set of points. They only work on a set where in one dimension e.g. x
xi < xi+1
For an arbitary set of points, e.g. an aeroplane flight path, where each point is a (longitude, latitude) pair, you will be better off simply modelling the aeroplane's journey with current longitude & latitude and velocity. By adjusting the rate at which the aeroplane can turn (its angular velocity) depending on how close it is to the next waypoint, you can achieve a smooth curve.
The resulting curve would not be mathematically significant nor give you bezier control points. However the algorithm would be computationally simple regardless of the number of waypoints and could produce an interpolated list of points at arbitrary granularity. It would also not require you provide the complete set of points up front, you could simply add waypoints to the end of the set as required.
I came up with the same problem and implemented it with some friends the other day. I like to share the example project on github.
https://github.com/johnjohndoe/PathInterpolation
Feel free to fork it.
Google "orthogonal regression".
Whereas least-squares techniques try to minimize vertical distance between the fit line and each f(x), orthogonal regression minimizes the perpendicular distances.
Addendum
In the presence of noisy data, the venerable RANSAC algorithm is worth checking out too.
In the 3D graphics world, NURBS are popular. Further info is easily googled.

Resources