Finding an eqauivalent point in a quadrilateral - javascript

I am trying to find the rough equivalent point from one quadrilateral to another.
quadrilateral equivalent point
What is a good method to find this point?
Any info in the right direction would be great.
Thanks

Let the points be [P1, P2, P3, P4] and assume they are transformed into [Q1, Q2, Q3, Q4] by means of an affine transformation of the form x -> Mx + b where M is a 2x2 matrix and b is a constant vector. The idea is to find M and apply the transformation to P to get Q.
Let v1 = P2 - P1, v2 = P3 - P1, w1 = Q2 - Q1, w2 = Q3 - Q1. Then M is the linear transformation that applies [v1, v2] onto [w1, w2]. One way to find M is by calculating the matrix product
M = S * T
where S is the 2x2 matrix whose columns are the vectors w1 and w2 and T is the inverse of the matrix whose columns are v1 and v2.
Regarding the displacement vector b, it can be calculated as
b = Q1 - M * P1
The clarification here is that all of this is correct only if the fourth points are consistent with the transformation, i.e., if
M * P4 + b = Q4
otherwise the Q-quadrilateral is not an affine transformation of the P-quadrilateral.

You can find the general barycentric coordinates of the point against the first quadrilateral, then applies the barycentric coordinates against the 2nd quadrilateral to find the "equivalent" point.
There are many different ways to compute the general barycentric coordinates for a point against a quadrilateral (or against a n-sided polygon). One of them is the Wachpress coordinates, which only works when the polygon is convex. For a convex polygon with vertices V0, V1,...Vn:
we can compute the Wachpress coordinates for point P within the polygon as
where A(a,b,c) is the signed area of triangle abc.
Then, we can compute the barycentric coordinates of P as
The equivalent point P* against the new polygon with vertices V*i (or quadrilateral in your case) can be computed as
P* = \summation(Wi * V*i) for i=0~n.

Related

How do I Calculate Control Point/Handle X-Position for a Cubic Bezier Curve if I have the Formula?

I have a curve that adheres to the bezier formula, and then I have to back-calculate the handle positions.
We know that the Po or Poy are [493.33970441 486.78826487 497.69599613 489.07543952] for Po, P1, P2, P3, through least squares interpolation. Now I need to find the handles Px positions.
P0 = (0, 493.33970441)
P1 = (P1x, 486.78826487)
P2 = (P2x, 497.69599613)
P3 = (1, 489.07543952)
I might not understand correctly, but I'd like to draw the position of where the handle is on the corresponding chart.

get a point on a bezier curve without guessing or brute force

I originally wanted to use four points (as a bezier Curve is defined with 4 points), but that forces me to brute force the position, so I tried a different approach i now need help with:
I have a start point P0, an end point P1 and slopes m0 and m1 which are supposed to give me the start/end slope to calculate a Bezier Curve inbetween them.
The Curve is supposed to be in the form of a function (3rd degree), since I need to get the height y of a given point x.
Using the HTML5Canvas i can draw a bezier curve no problem and using this function
that allows me to calculate any given point given a percentage of the way i can get the center point of the curve. But I don't need it depending on t but rather the y depending on x, so not halfway of the curve but halfway of the x distance between P0 and P1.
Image to visualize:
Left is what i can calculate, right is what i need.
I've been trying to calculate the cubic function given the two points P0, P1 as well as the slopes m0, m1, which results into four equations which i can't seem to be able to solve with only variable inputs. I've also tried to use the above function to calculate the t using the x value (which is known), but no dice there either.
I need to avoid using approximations or costly loops for these calculations as they are performed many times a second for many objects, thus this answer is not feasible for me.
Any help is appreciated.
I've encountered the same problem in a project I'm working on. I don't know of a formula to get the y coordinate from the x, and I suspect you'll have trouble with that route because a bezier curve can have up to 3 points that all have the same x value.
I would recommend using the library BezierEasing, which was designed for this use case and uses various performance enhancing techniques to make lookups as fast as possible: https://github.com/gre/bezier-easing
To solve this problem, you need to rewrite Bezier equation in power polynomial form
X(t) = t^3 * (P3.X-3*P2.X+3*P1.X-P0.X) +
t^2 * (3*P0.X + 6*P1.X+3*P2.X) +
t * (3*P1.X - 3P2.X) +
P0.X
if X(t) = P0.X*(1-ratio) + P3.X*ratio
then
let d = ratio * (P0.X - P3.X)
and solve cubic equation for unknown t
a*t^3 + b*t^2 + c*t + d = 0
JS code here
Then apply calculated t parameter (there might be upto three solutions) to Y-component and get point coordinates. Note that formulas are close (no loops) and should work fast enough
Thank you to everyone that answered before, those are generally great solutions.
In my case I can be 100% sure that I can convert the curve into a cubic function, which serves as the approximation of the bezier curve using the result of this calculation.
Since i have control over my points in my case, I can force the P0 to be on x=0, which simplifies the linear system calculations and thus allows me to calculate the cubic function much easier like this:
let startPoint: Utils.Vector2 = new Utils.Vector2(0, 100);
let endPoint: Utils.Vector2 = new Utils.Vector2(100, 100);
let a: number, b: number, c: number, d: number;
function calculateFunction() {
let m0: number = 0;
let m1: number = 0;
a = (-endPoint.x * (m0 + m1) - 2 * startPoint.y + 2 * endPoint.y) / -Math.pow(endPoint.x, 3);
b = (m1 - m0 - 3 * a * Math.pow(endPoint.x, 2)) / (2 * endPoint.x);
c = m0;
d = startPoint.y;
}

How to find the last point coordinate of a triangle based on having two point and all the distances in javascript?

I am trying to figure out the (x,y) position of the s2 node from the given example.
1
With trilateration I was able to calculate the first node s1 position based on the fixed anchors. Now I am trying to calculate the s2 node possible coordinates, what I have is:
Coordinates of two points:
A2:{y:0,x:4}
S1:{y:2,x:2}
Distances:
A2-S2: 2
S1-S2: 2
A2-S1: 2
Is there a way to calculate the possible positions of the s2 node based on this data in JavaScript? This should work on any type of triangle.
Update:
I think I found a solution, I can threat the 2 known position as the centre of two circle and the distances to the unknown point as radius, than I have to calculate the intersection of the two circle to get the possible coordinates.
A JavaScript function that returns the x,y points of intersection between two circles?
You have two known points A and B, unknown point C and distances dAC and dBC (dAB is useless). So you can build equation system
(C.X - A.X)^2 + (C.Y - A.Y)^2 = dAC^2
(C.X - B.X)^2 + (C.Y - B.Y)^2 = dAB^2
and solve it for C.X and C.Y (there are possible two, one and zero solutions).
Note that it is worth to shift coordinates by (-A.X, -B.X) to get simpler equations and solution, then add (A.X, B.X) to the solution coordinates

How can I make squares?

I'm trying to generate random, convex, non-self-intersecting polygons - quadrilaterals specifically.
I've gotten as far as:
function randquad(){
var bodyDef = new b2BodyDef,
fixDef = new b2FixtureDef,
x=0, y=0;
fixDef.density = Math.random();
fixDef.friction = Math.random();
fixDef.restitution = Math.random()*0.3;
bodyDef.type = b2Body.b2_dynamicBody;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsArray([
new b2Vec2(x, y),
new b2Vec2(x+=Math.random()*2, y+=Math.random()*2*(Math.random()<0.5?1:-1)),
new b2Vec2(x+=Math.random()*2*(Math.random()<0.5?1:-1), y+=Math.random()*2),
new b2Vec2(x-=Math.random()*2, y+=Math.random()*2*(Math.random()<0.5?1:-1))
]);
bodyDef.position.x = Math.random() * 10;
bodyDef.position.y = 0;
world.CreateBody(bodyDef).CreateFixture(fixDef);
}
I'm working with Box2D web; however, this question is not limited to it, or javascript - its a broader one that is more mathematical.
I want to get 4 points that, in a sequence, make the shape I'm looking for.
With the code I've written I often get the desired shape; however, I do still get self-intersecting shapes. At the moment I'm not too fussed about the shapes being convex.
The reason I need such shapes is because it seems they're the only ones box2d web likes.
Any 4 points can make a non-self-intersecting quadrilateral right?
Should I generate 4 initially, and sort them into a sequence that works?
Whats the best/most efficient manner in which to approach this?
-- Original Question Title: Random Quadrilateral Generation
You could start from the fact that if you take 3 random points, they will always form a convex, non-intersecting triangle (provided the points are all different). Then you can just pop out one of the edges by adding a fourth point a random distance along the last edge, and pushing it away from the center of the triangle by a random amount.
Start off by generating a random triangle by generating 3 random points: A, B, C
Choose a random number between 0 and 1, and use it to calculate a point D somewhere along the line between C and A
Calculate the centroid of the triangle by averaging A, B, C
Calculate another random number between 1 and n (say 2)
Calculate the vector from the centroid to D (subtract the centroid from D), and multiply it by this second random number, then add back to the centroid. This will produce your fourth point.
I'm not sure if you have any aesthetic requirements (e.g. no excessively pointy shapes) but you could play around with the random number generation a bit to get the results you like. For example in the second step you could choose a random number between 0.2 and 0.8, for example, so the points aren't too close together. You can also change the value of n in the fourth step.
Another issue is winding. With this method, half the quads will have a clockwise winding and have will be counter-clockwise. If you need a particular winding you can do a winding test (sign of dot product of BC with normal of AB), and if it's not the way you want then just reflect all the points on one axis.
If you take your points from the perimeter of a circle all the vertices will be convex.
Knowing this we can program a loop to branch out to a non-existant circle and generate corners that'll always produce a convex shape.
angles=[];
for (var i = 4; i--;) angles.push(Math.random()*2*Math.PI);
Now the angles need to be sorted so when the shape is created, clockwise, they're chosen in order of angle size.
This will stop points crossing / self intersection of the shape.
angles.sort()
Now you can create the shape using the triganometric functions cos and sin, these will convert the angle to actual co-ordinates.
polygon([
vector(Math.cos(angles[0]), Math.sin(angles[0])),
vector(Math.cos(angles[1]), Math.sin(angles[1])),
vector(Math.cos(angles[2]), Math.sin(angles[2])),
vector(Math.cos(angles[3]), Math.sin(angles[3]))
]);`

How to find the middle point of an arc slice?

I have a slice of a circle (that is made of moveTo,lineTo,arc,etc) and need to find the middle point of the slice.
What is the math behind finding the point shown in the image below?
It looks "centroid" of the sector to me.
The co-ordinates of it (with x axis along the radius passing through the centroid and origin at the centre)
centroidX = (4/3)r(sin(A)/A)
centroidY = 0
where 'A' is the angle made by the arc at the centre(in radians) and 'r' is the radius.
EDIT:
This is sort of a formula which can be easily derived.
Geometric Centroid of any shape is average(weighted mean) of all it's points.
In physics, centroid(AKA centre of mass) of an object is the point at which the mass of the whole object can be assumed to be concentrated(eg, the object can be balanced on a needle at the centroid). There are formulae which can be directly used for regular shapes. For irregular shapes, it is calculated by integration.
It's basic logic is adding x co-ordinates of all the points and dividing by total no. of points, which gives x co-ordinate of the centroid and similar for y co-ordinate.
As the points on a shape are not discrete, integration is used.
Let C is center point, P1 and P2 are points at circumference, and slice angle is smaller then Pi (180 deg).
One possibility:
X = C + Radius/2 * UnitVector(P1 + P2 - 2*C)
Another:
X = 1/3 * (P1 + P2 + C)
(It depends on exact requirements)

Categories