Is it possible to infer bearing from relative movement of points - math

Given an initial set of coords in a 2d space:
A = 0,0
B = 0,20
C = 10,10
Then after an interval a moved set of points, i.e
A = 0,0
B = 0,20
C = 5,5
How do I calculate to what degree left or right Point B has moved in relation to point A.
Context:
Say three people are standing in a field, its dark and they cant see each other, no internet, no gps, but the devices they are holding know of the distances between nodes, and we can calculate the basic triangle. If I am at point A and want to get to point B, in which direction do I travel?

use the dot or cross product to calcualte the position inside the two triangles, the calculate the diffrence.
Or if you want there are answers on stack overflow about points inside triangles
that can be found here
float sign (fPoint p1, fPoint p2, fPoint p3)
{
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}
bool PointInTriangle (fPoint pt, fPoint v1, fPoint v2, fPoint v3)
{
bool b1, b2, b3;
b1 = sign(pt, v1, v2) < 0.0f;
b2 = sign(pt, v2, v3) < 0.0f;
b3 = sign(pt, v3, v1) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}

Related

Finding the new relative position of a point against the line after moved together

I am working on a drawing application. I summerize the main question to a tiny scenario:
User draws the line A1-B1 and also the point M1. Now user moves the line A1-B1 to a new position A2-B2 while the point M1 also should move with the line (like a rigid body). How can I calculate the new position of point M2?
I know it is possbile with complex calucations on lines or circles conjuction and finally detemrining if the new point is on the right or left of line (this question) etc. But as I want to recalculate live on any steps of dragging, I guess there should be a shortcut and light solution which all modeling softwares use. Is there really a shortcut formula rahter than the line or circle conjuctions?
To summerize the problem again I am looking for a light function with given A1,B1,A2,B2,M1 and looking for M2 position (two separate formula for x and y)
M2 = f(A1,B1,A2,B2,M1)
My guess: I think finding the center and the angle of rotation is one of the best options but I don't know again if there is a shotcut function to find them.
Edit: I prefer to implement it in an online website, so if there is a ready javascript library, it would be helpful, However I am now just looking for the mathematical logic.
Start with A1 and B1.
D = B1 - A1
C1 = D/|D|
Rotate C1 90 degrees counter-clockwise to get C'1:
C1 = (cx, cy)
C'1 = (-cy, cx)
Now take M1 - A1 and measure it against C1 and C'1:
j = (M1 - A) · C1
k = (M1 - A) · C'1
Now it's easy to prove:
M1 = A1 + j C1 + k C'1
So j and k tell you where M1 is, given A1 and B1.
When you get A2 and B2, use them to construct C2, rotate it to get C'2, and then you'll have:
M2 = A2 + j C2 + k C'2
I'm assuming points are objects which have x and y values. Like this:
A1 = {x: 100, y:100}
Here's a lightweight solution:
function reposition(A1,A2,B1,B2,M1)
{
//Getting the Angle Between Lines
var angle = Math.atan2(B2.y-B1.y, B2.x-B1.x)-Math.atan2(A2.y-A1.y, A2.x-A1.x);
//Rotating the point
var xdif = M1.x-A1.x; //point.x-origin.x
var ydif = M1.y-A1.y; //point.y-origin.y
//Returning M2
return {x:B1.x + Math.cos(angle) * xdif - Math.sin(angle) * ydif, y: B1.y + Math.sin(angle) * xdif + Math.cos(angle) * ydif}
}

Minimum distance between two circles along a specified vector on a cartesian plane

I am trying to solve the following problem (I am using Matlab, though pseudo-code / solutions in other languages are welcome):
I have two circles on a Cartesian plane defined by their centroids (p1, p2) and their radii (r1, r2). circle 1 (c1 = [p1 r1]) is considered 'dynamic': it is being translated along the vector V = [0 -1]. circle 2 (c2 = [p2 r2]) is considered 'static': it lies in the path of c1 but the x component of its centroid is offset from the x component of c2 (otherwise the solution would be trivial: the distance between the circle centroids minus the sum of their radii).
I am trying to locate the distance (d) along V at which circle 1 will 'collide' with circle 2 (see the linked image). I am sure that I can solve this iteratively (i.e. translate c1 to the bounding box of c2 then converge / test for intersection). However, I would like to know if there is a closed form solution to this problem.
Shift coordinates to simplify expressions
px = p1.x - p2.x
py = p1.y - p2.y
And solve quadratic equation for d (zero, one, or two solutions)
px^2 + (py - d)^2 = (r1 + r2)^2
(py - d)^2 = (r1 + r2)^2 - px^2
d = py +/- Sqrt((r1 + r2)^2 - px^2)
That's all.
As the question title does not match the question and accepted answer which is dependent on a fixed vector {0, -1}, or {0, 1} rather than an arbitrary vector I have added another solution that works for any unit vector.
Where (See diagram 1)
dx, dy is the unit vector of travel for circle c1
p1, p2 the centers of the moving circle c1 and static circle c2
r1, r2 the radius of each circle
The following will set d to the distance c1 must travel along dx, dy to collide with c2 if no collision the d will be set to Infinity
There are three cases when there is no solution
The moving circle is moving away from the static circle. u < 0
The moving circle never gets close enough to collide. dSq > rSq
The two circles are already overlapping. u < 0 luckily the math makes
this the same condition as moving away.
Note that if you ignore the sign of u (1 and 3) then d will be the distance to first (causal) contact going backward in time
Thus the pseudo code to find d
d = Infinity
rSq = (r1 + r2) ^ 2
u = (p1.x - p2.x) * dx + (p1.x - p2.x) * dy
if u >= 0
dSq = ((p2.x + dx * u) - p1.x) ^ 2 + ((p2.y + dy * u) - p1.y) ^ 2
if dSq <= rSq
d = u - (rSq - dSq) ^ 0.5
The point of contact can be found with
cpx = p1.x + dx * d;
cpy = p1.x + dy * d;
Diagram 1

Rotate all points to align with a vector

I have a vector v = (x,y,z), and I want to rotate all points such that the point (x,y,z) = (0,0,sqrt(x^2 + y^2 + z^2). In other words, I want to make the direction of the vector v be the z axis, and rotate all points such that this is true.
I want the point (1,1,0) to go to (0,0,sqrt(2)), and the point (0,0,1) to go to (-1/(sqrt(2)),-1/sqrt(2),0) given a v of (1,1,0).
I am working in unity3d's left handed axis system, where y is vertical.
My current method is this, using with v = (vx,vy,vz) and x,y,z being the point to be rotated.
float vx = 1;
float vy = 1;
float vz = 0;
float c1 = -vz/(sqrt(vx*vx + vz*vz));
float c2 = -sqrt(vx*vx + vz*vz)/sqrt(vx*vx + vy*vy + vz*vz);
float s1 = -vx/(sqrt(vx*vx + vz*vz));
float s2 = -vy/sqrt(vx*vx + vy*vy + vz*vz);
float rx = x * c1 + y*s1*s2 - z*s1*c2;
float ry = x * 0 + y*c2 + z * s2;
float rz = x * s1 - y*s2*c1 + z*c1*c2;
You are looking for a 3x3 Matrix f with fv=(0,0,1), |x|=|fx|; this needs
( t1 t2 t3 )
f = ( u1 u2 u3 )
( w1 w2 w3 )
where w := v / |v|, and t, u, w are pairwise orthogonal and |t|=|u|=|w|=1.
Chosing t and u depends on what you want to do, but if you just need any t and u, get some via the 3d cross product.
I found the answer, find axis of rotation by taking cross product of (0,0,1) then use this as the axis of rotation with the angle being the angle between the vector (0,0,1) and (vx,vy,vz).
http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle

How to calculate coordinates of third point in a triangle (2D) knowing 2 points coordinates, all lenghts and all angles [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I have a triangle and I know the coordinates of two vertices: A=(x1,y1),B=(x2,y2)
All the angles: ABC=90∘,CAB=30∘ and BCA=60∘ and all the edge lengths. How can I find the coordinates of the third vertex C=(x3,y3)?
I know there are two solutions (I want both).
You know p1 and p2. You know the internal angles.
Make a ray from p1 trough p2, and rotate it CW or CCW 30° around p1.
Make a line trough p1 and p2, and rotate it 90° around p2.
Calculate the intersections.
You get the points:
x3 = x2 + s*(y1 - y2)
y3 = y2 + s*(x2 - x1)
and
x3 = x2 + s*(y2 - y1)
y3 = y2 + s*(x1 - x2)
where s = 1/sqrt(3) ≈ 0.577350269
In a 30-60-90 right triangle, smallest leg (the smallest side adjacent the 90 degree angle) has length of 1/2 of the hypotenuse (the side opposite to 90 degree angle), so since you have the side lengths, you can determine which leg is the line segment AB.
From that you deduce where do the angles go.
Then to compute the coordinate you just need to pick the point on the circle of the radius with the correct radius length at the correct angle.
Two solutions come from measuring the angle clock-wise or counter-clockwise, and result in symmetrical triangles, with the edge AB being the line of symmetry.
Since you already have given the angles, compute the length of AB via quadratic formula
L(AB) = Sqrt[(x1-x2)^2 + (y1-y2)^2].
Now, let x = L(AC) = 2*L(BC) so since it is the right triangle,
L(AC)^2 = L(BC)^2 + L(AB)^2,
x^2 = (0.5x)^2 + L(AB)^2, so L(AB) = x*Sqrt[3]/2,
and since you already computed L(AB) you now have x.
The angle of the original AB is a = arctan([y2-y1]/[x2-x1]).
Now you can measure 30 degrees up or down (use a+30 or a-30 as desired)
and mark the point C on the circle (centered at A) of radius x (which we computed above) at the angle a +/- 30.
Then, C has coordinates
x3 = x1 + x*cos(a+30)
y3 = y1 + x*sin(a+30)
or you can use (a-30) to get the symmetrical triangle.
Here is the code to return points of full polygon if two points and number of sides are provided as input.
This is written for Android(Java) and the logic can be re-used for other languages
private static final float angleBetweenPoints(PointF a, PointF b) {
float deltaY = b.y - a.y;
float deltaX = b.x - a.x;
return (float) (Math.atan2(deltaY, deltaX));
}
private static PointF pullPointReferenceToLineWithAngle(PointF a, PointF b,
float angle) {
float angleBetween = angleBetweenPoints(b, a);
float distance = (float) Math.hypot(b.x - a.x, b.y - a.y);
float x = (float) (b.x + (distance * Math.cos((angleBetween + angle))));
float y = (float) (b.y + (distance * Math.sin((angleBetween + angle))));
return new PointF(x, y);
}
private static List<PointF> pullPolygonPointsFromBasePoints(PointF a,
PointF b, int noOfSides) {
List<PointF> points = new ArrayList<>();
points.add(a);
points.add(b);
if (noOfSides < 3) {
return points;
}
float angleBetweenTwoSides = (float) ((((noOfSides - 2) * 180) / noOfSides)
* Math.PI / 180);
for (int i = 3; i <= noOfSides; i++) {
PointF nextPoint = pullPointReferenceToLineWithAngle(
points.get(i - 3), points.get(i - 2), angleBetweenTwoSides);
points.add(nextPoint);
}
return points;
}
Usage is onDraw method:
PointF a = new PointF(100, 600);
PointF b = new PointF(300, 500);
int noOfSides = 3;
List<PointF> polygonPoints = pullPolygonPointsFromBasePoints(a, b,
noOfSides);
drawPolyPoints(canvas, noOfSides, polygonPoints);
This is a right angled triangle. The angle ABC is 90 degrees, so calculate the vector joining A to B and call this AA and normalise it:
AA = (x2-x1,y2-y1) / |(x2-x1,y2-y1)|
A unit vector perpendicular to AA is given by
BB = (-(y2-y1),x2-x1) / |(x2-x1,y2-y1)|
Because AC is perpendicular to AB all you can obtain your first point P1 as
P1 = (x2,y2) + K * BB
where K is the scalar value equal to the length of side AC (which you say you already know in the question). Your second solution point P2 is then simply given by going in the negative BB direction
P2 = (x2,y2) - K * BB

Non-axis aligned scaling

Finding a good way to do this has stumped me for a while now: assume I have a selection box with a set of points in it. By dragging the corners you can scale the (distance between) points in the box. Now for an axis aligned box this is easy. Take a corner as an anchor point (subtract this corner from each point, scale it, then add it to the point again) and multiply each points x and y by the factor with which the box has gotten bigger.
But now take a box that is not aligned with the x and y axis. How do you scale the points inside this box when you drag its corners?
Any box is contained inside a circle.
You find the circle which binds the box, find its center and do exactly the same as you do with an axis aligned box.
You pick one corner of the rectangle as the origin. The two edges connected to it will be the basis (u and v, which should be perpendicular to each other). You would need to normalize them first.
Subtract the origin from the coordinates and calculate the dot-product with the scaling vector (u), and with the other vector (v). This would give you how much u and v contributes to the coordinate.
Then you scale the component you want. To get the final coordinate, you just multiply the the (now scaled) components with their respective vector, and add them together.
For example:
Points: p1 = (3,5) and p2 = (6,4)
Selection corners: (0,2),(8,0),(9,4),(1,6)
selected origin = (8,0)
u = ((0,2)-(8,0))/|(0,2)-(8,0)| = <-0.970, 0.242>
v = <-0.242, -0.970>
(v is u, but with flipped coordinates, and one of them negated)
p1´ = p1 - origin = (-5, 5)
p2´ = p2 - origin = (-2, 4)
p1_u = p1´ . u = -0.970 * (-5) + 0.242 * 5 = 6.063
p1_v = p1´ . v = -0.242 * (-5) - 0.970 * 5 = -3.638
Scale p1_u by 0.5: 3.038
p1_u * u + p1_v * v + origin = <5.941, 4.265>
Same for p2: <7.412, 3.647>
As you maybe can see, they have moved towards the line (8,0)-(9,4), since we scaled by 0.5, with (0,8) as the origin.
Edit: This turned out to be a little harder to explain than I anticipated.
In python code, it could look something like this:
def scale(points, origin, u, scale):
# normalize
len_u = (u[0]**2 + u[1]**2) ** 0.5
u = (u[0]/len_u, u[1]/len_u)
# create v
v = (-u[1],u[0])
ret = []
for x,y in points:
# subtract origin
x, y = x - origin[0], y - origin[1]
# calculate dot product
pu = x * u[0] + y * u[1]
pv = x * v[0] + y * v[1]
# scale
pu = pu * scale
# transform back to normal space
x = pu * u[0] + pv * v[0] + origin[0]
y = pu * u[1] + pv * v[1] + origin[1]
ret.append((x,y))
return ret
>>> scale([(3,5),(6,4)],(8,0),(-8,2),0.5)
[(5.9411764705882355, 4.2647058823529411), (7.4117647058823533, 3.6470588235294117)]
Let's say that the box is defined as a set of four points (P1, P2, P3 and P4).
For the sake of simplicity, we'll say you are dragging P1, and that P3 is the opposite corner (the one you are using as an anchor).
Let's label the mouse position as M, and the new points you wish to calculate as N1, N2 and N4. P3 will, of course, remain the same.
Your scaling factor can be simply computed using vector subtraction and the vector dot product:
scale = ((M - P3) dot (P1 - P3)) / ((P1 - P3) dot (P1 - P3))
And the three new points can be found using scalar multiplication and vector addition:
N1 = scale*P1 + (1 - scale)*P3
N2 = scale*P2 + (1 - scale)*P3
N4 = scale*P4 + (1 - scale)*P3
edit: I see that MizardX has answered the question already, so my answer is here to help with that difficult explanation. I hope it helps!
edit: here is the algorithm for non-proportional scaling. In this case, N1 is equal to M (the point being dragged follows the mouse), so the only points of interest are N2 and N4:
N2 = ((M - P3) dot (P2 - P3)) / ((P2 - P3) dot (P2 - P3)) * (P2 - P3) + P3
N4 = ((M - P3) dot (P4 - P3)) / ((P4 - P3) dot (P4 - P3)) * (P4 - P3) + P3
where * represents scalar multiplication
edit: Here is some C++ code which answers the question. I'm sure this question is long-dead by now, but it was an interesting problem, and I had some fun writing the code.
#include <vector>
class Point
{
public:
float x;
float y;
Point() { x = y = 0; }
Point(float nx, float ny) { x = nx; y = ny; }
};
Point& operator-(Point& A, Point& B) { return Point(A.x-B.x, A.y-B.y); }
Point& operator+(Point& A, Point& B) { return Point(A.x+B.x, A.y+B.y); }
Point& operator*(float sc, Point& P) { return Point(sc*P.x, sc*P.y); }
float dot_product(Point A, Point B) { return A.x*B.x + A.y*B.y; }
struct Rect { Point point[4]; };
void scale_points(Rect box, int anchor, Point mouse, vector<Point> points)
{
Point& P3 = box.point[anchor];
Point& P2 = box.point[(anchor + 1)%4];
Point& P1 = box.point[(anchor + 2)%4];
Point& P4 = box.point[(anchor + 3)%4];
Point A = P4 - P3;
Point aFactor = dot_product(mouse - P3, A) / dot_product(A, A) * A;
Point B = P2 - P3;
Point bFactor = dot_product(mouse - P3, B) / dot_product(B, B) * B;
for (int i = 0; i < points.size(); i++)
{
Point P = points[i] - P3;
points[i] = P3 + dot_product(P, aFactor) + dot_product(P, bFactor);
}
}

Resources