Cheaply determine which of 2 Bezier Curves is longer - javascript

In my situation I need to compare the length of 2 bezier curves. I do not need to compute the actual length of either curve. I merely want to cheaply compare which of the 2 is longer. My assumptions for this method are as followed:
Both Bezier curves to compare are same dimension(number of control points)
The dimension of the curves could be any number greater than 2
I need to output which of the 2 curves is longer (either if equal)
My original thought, was to just add the lengths of control points ie:
distance(p0, p1) + distance(p1, p2) + distance(p2, p3)...
And It seems to work decently for lower order bezier curves. However I sure that this would not scale well in higher order curves.
I ended with a solution that adds the distance between each control point projected on the curve(basically take number of control points / index of point and using that value as T), and seems to work on some higher dimension curves.
I can't imagine I am the first person to want to do this, So to reiterate does anyone know of the right way to do this?

Related

How to detect polygon edge when implementing a plane sweep algorithm?

I am working in javascript and trying to implement an algorithm that triangulates a polygon (something convex or concave but assumed to be a simple polygon, not self crossing and without holes).
I have found a solution on the web but it is only in pseudocode and I am trying to implement it. ( source of the algorithm : https://sites.cs.ucsb.edu/~suri/cs235/Triangulation.pdf page 19).
The first step is to partition the polygon into trapezoids with a plane sweep algorithm, which is described as "At each vertex, extend vertical line until it hits a polygon edge. Each face of this decomposition is a trapezoid; which may degenerate into a triangle."
Considering that my polygon is set of coordinates, how do I know that my line is crossing the polygon ?
I was thinking that I could do something like
take the horinzontal x coordinate of my vertex as x1
take each pair of sucessive vertices (x2, y2, x3, y3)
test if they are on each side of the line (x2 < x1 and x1 < x3 or the opposite)
if yes calculate the equation for the line between them
use this equation to calculate y1
but it sounds like overkill since it has a O(n²) complexity and the pseudocode announces O(n*log(n)). And I can't stop when I have found a solution since my polygone might "double back" and there would be multiple points of crossing.
Is there another way to find the points where the line crosses the polygon?
(Or a simple way to triangulate the polygon in the first place)
There might be easier ways to solve it, but this might be one approach:
Make use of the Bentley Ottman algorithm for finding intersections in a set of line segments. Since your polygon is not self-intersecting, you can just add your sweep segments and find its intersections in O((n + k) log n) time, where k is the number of intersections. As long as the total number of intersections is O(n) (which will be the case if your polygon is not too crazy shaped), the resulting time complexity should be O(n log n).

Cubic bezier function for finding progress given time and two control points

I am trying to find a JS algorithm to find the ypos of a cubic bezier given the xpos. the first and last control points will be (0,0) and (1,1) and it should throw an error if any of the inputted control points' xpos is less than 0 or greater than 1, just like in CSS. the function will be called like
cubicBezier(p1x, p1y, p2x, p2y, time)
I spent like half an hjour searching it on google but nothing seemed to work.. I only fornd a buch of mathematical formulas when I was looking for an algorithm. Even when I turned my eyes to stackoverflow I couldn't find anything other than complex mathematical formulas and stuff in c++
the top left point is going to be p1 and the other point is p2.

Concept of a sript to calculate mouse velocity

Hi guys:)Could someone explain me this code?I am trying to understand but there is nothing to do.Why this line of code?
Math.sqrt(x_dist*x_dist+y_dist*y_dist)/interval;
Isn't sufficent this?
x_dist+y_dist/interval;
I don't understand the concept of this code...
https://jsfiddle.net/vnodkumar1987/ER8qE/
The first example calculates the hypotenuse, and in so doing achieves an absolute velocity value of the mouse vector.
The second example will give a bad result unless both x_dist and y_dist are positive. In other words, if you were moving down and left, or up and right, the second example would have a subtractive effect, and not represent the true overall velocity. In the case of up and left, the velocity would not only be proportionately incorrect (only useful for comparison purposes), but also result negative sign that you would have to account for. (I am assuming 0,0 represents the upper left of the mouse-able area and x_max,y_max to be the lower right.)
The Math.sqrt may not be necessary if you are just scaling proportionate velocity, but it certainly is if you want to know true pixels/interval. You would also have to take into account how big a variable container you are working with, but I'm sure it would all fit into a double... unless you were looking for extreme precision.
Imagine you travel in a straight line so that you end up at a point 3 miles West, and 4 miles South in exactly 1 hour. The velocity answer is not 3+4=7 miles per hour, nor is it-3+4=1 miles per hour. The correct answer of absolute velocity is the hypotenuse, which would be 5 mph. sqrt(west^2+south^2)
Example #1 would be the proper code. Example #2 could be roughly used if you can ignore the sign, and you needed the code to execute very quickly.
The velocity is distance_travelled/time_taken.
Say the pointer moves from (x1,y1) to (x2,y2) as shown in the figure above. The distance travelled is not the sum of the x and y distances.
Summing up x and y assumes that the pointer went from (x1,y1) to (x2,y1) and then from (x2,y1) to (x2,y2). i.e. the sum of the lengths of the 2 blue lines. But what you need is the length of the black line.
The actual distance travelled is d as shown in the figure. Using Pythagorean theorem, d^2 = x_dist^2 + y_dist^2.
Which leaves you with the line of code you have in the question for the speed
Math.sqrt(x_dist*x_dist+y_dist*y_dist)/interval;
You are making a pythagorean triangle with the two catethus being x_dist and y_dist, which are the distance the mouse moved in each of X and Y axis each frame. What that line of code does is to get the magnitude of the delta position vector of the mouse and divide it by some scalar value.
Also, note that sqrt(a^2 + b^2) does NOT equal a + b.
EDIT: Not velocity, but delta position.

Accounting for vertical slope

I'm not a programmer primarily, so this might be a simple answer.
I'm working on a script in Illustrator where you select three points and then it does stuff. First it makes a triangle. Then, it recreates two of the line segments in the triangle and rotates them 90 degrees. Then, I find the intersect of those points so that I can make a circumcircle.
I'm actually moving along quite well, but the only problem I don't know how to solve at the moment is when two points that comprise the triangle have the same y-coordinates. When I make the perpendicular line, that line is vertical and therefore has no slope. It throws an error.
How do I account for a vertical slope with JavaScript? I was thinking about something along the lines of, "if the slope is NaN, then set the slope value to 9999999" or something like that, but this seemed a bit crude. Any better options?
You could normalise your gradient in the range -1 to 1. Anything larger than 1, or a NaN, is clamped at 1. The same goes for negative numbers, but with -1.

Generate random 5d vector of given magnitude

Given a five dimensional space, I would like to generate 100 vectors, all with a fixed magnitude=M, where the components values are randomly distributed.
I was originally thinking of starting off with a unit vector and then applying a rotation matrix, with random parameters for the 10 degrees of freedom ... Would this work? and how?
Any nice way of doing this in Javascript...?
cheers for any pointers!
Here is the Monte Carlo algorithm that I would use (I do not know Javascript well enough to code in it off the top of my head):
Generate random values in the range from -1 to 1 for each of the five dimensions.
Calculate the Magnitude M, if M=0 or M>1 then reject these values and return to step #1.
Normalize the vector to have a Magnitude of 1 (divide each dimension by M).
That should give you random unit vectors evenly distributed over the 5-dimensional super-sphere surface.
The question has been asked: "Why reject the vector if M>1?"
Answer: So that the final vectors will be uniformly distributed across the surface of the unit 5-sphere.
Reasoning: What we are generating in the first step is a set of random vectors that are uniformly distributed within the volume of the unit 5-cube. Some of those vectors are also within the volume of the unit 5-sphere and some of them are outside of that volume. If normalized, the vectors within the 5-sphere are evenly distributed across its surface, however, the ones outside it are not at all evenly distributed.
Think about it like this: Just as with a normal 3-dimensional Unit Cube and Unit Sphere, or even the Unit Square and the Unit Circle, the Unit 5-Sphere is wholly contained within the Unit 5-Cube, which touches only at the five positive unit dimension axis points:
(1,0,0,0,0)
(0,1,0,0,0)
(0,0,1,0,0)
(0,0,0,1,0)
(0,0,0,0,1)
and their corresponding negative unit axis points. This is because these are the only points on the surface of the cube that have a magnitude (distance from the origin) of 1, at all other points, the 5-cube's surface has a distance from the origin that is greater than 1.
And this means that there are many more points between (0,0,0,0,0) and (1,1,1,1,1) than there are between (0,0,0,0,0) and (1,0,0,0,0). In fact about SQRT(5) or aprx. 2.25 times more.
And that means that if you included all of the vectors in the unit 5-cube, you would end up with more than twice as many results "randomly" mapping to about (0.44,0.44,0.44,0.44,0.44) than to (1,0,0,0,0).
For those who are challenging (without foundation, IMHO) that this results in a uniform distribution across the surface of the 5-D Sphere, please see the alternative method in this Wikipedia article section: https://en.wikipedia.org/wiki/N-sphere#Uniformly_at_random_on_the_(n_%E2%88%92_1)-sphere
The problem with sampling from a unit hypercube in 5-dimeensions and then re-scaling, is points in some directions (towards the corners of the hypercube) will be over sampled.
But if you use a rejection scheme, then you lose too many samples. That is, the volume of a unit hypercube in 5-d is pi^2*(8/15) = 5.26378901391432. Compare that to the volume of a unit hyper-cube in 5 dimensions that will just contain the sphere. That hypercube has volume 32. So if you reject points falling outside the sphere, you will reject
1 - 5.26378901391432/32 = 0.835506593315178
or roughly 83.5% of the points get rejected. That means you will need to sample roughly 6 points on average before you do find a sample that is inside the 5-sphere.
A far better idea is to sample using a unit normal sample, then rescale that vector of points to have unit norm. Since the multi-variate normal distribution is spherically symmetric, there is no need for rejection at all.
Here are some approaches, it is for unit vectors but you can just multiply by M:
http://burtleburtle.net/bob/rand/unitvec.html
I'd recommend assigning random numbers between -1 and +1 for each element. Once all elements for a vector have been assigned, then you should normalize the vector. To normalize, simply divide each element by the magnitude of the overall vector. Once you've done that, you've got a random vector with a magnitude of 1. If you want to scale the vectors to magnitude M, you just need to multiply each element by M.
Picking without rejections (6 times faster)
From Mathworld and a link posted by Bitwise:
If you choose n numbers with a normal distribution, treat those as coordinates, and normalize the resulting vector into a unit vector, this chooses a uniformly distributed unit vector in n dimensions. - Burtleburtle (ht Bitwise)
As Bitwise points out, that should be multiplied by the desired magnitude.
Note that there is no rejection step here; the distributions themselves have dealt with the necessary bias towards zero. Since the normal distribution and a semi-circle are not the same shape, I wonder if RBarryYoung's answer really gives a uniform distribution on the surface of the sphere or not.
Regarding uniform hypercube picking with hypersphere rejection (RBarryYoung's answer)
The Mathworld article includes a description of using 4 random numbers picked from uniform distributions to calculate random vectors on the surface of a 3d sphere. It performs rejection on the 4d vector of random numbers of anything outside the unit hypersphere, as RBarryYoung does, but it differs in that it (a)uses an extra random number and (b)performs a non-linear transform on the numbers to extract the 3d unit vector.
To me, that implies that uniform distributions on each axis with hypersphere rejection will not achieve a uniform distribution over the surface of the sphere.

Categories

Resources