I have a line (P1, P2), and a point on that line (midpoint). What equation can I used to find the perpendicular line of line (P1, P2), that passes through midpoint. The point labelled with a '?' is unknown. I do not wish to use angles, only the 3 points given (P1, P2, midpoint). The line P1, P2 can be of any orientation/angle.
Thanks in advance.
Let define vector
D = P2 - P1 (dx=x2-x1, dy = y2-y1)
and middle point
mx = (x2+x1)/2
my = (y2+y1)/2
Perpendicular to D vector
PD = (-dy, dx)
Unit (normalized) perpendicular vector
U = (-dy / L, dx / L)
where
L = Sqrt (dx * dx + dy * dy)
And coordinates of point lying at distance F from the middle are
x = mx + U.x * F
y = my + U.y * F
or (for point at another side)
x = mx - U.x * F
y = my - U.y * F
Coordinates of P1: (x1,y1)
Coordinates of P2: (x2,y2)
Coordinates of midpoint: ( (x1+x2)/2 , (y1+y2)/2)
Slope of the P1P2 line: (y1-y2)/(x1-x2)
Slope of any perpendicular line to P1P2: (x2-x1)/(y1-y2)
Equation of the red line: y - (y1+y2)/2 = ((x2-x1)/(y1-y2))*(x - (x1+x2)/2)
If you have the actual values of coordinates of P1 y P2, then just make a substitution.
I come accross a math problem about Interactive Computer Graphics.
I summarize and abstract this problem as follows:
I'm going to rotation a 3d coordinate P(x1,y1,z1) around a point O(x0,y0,z0)
and there are 2 vectors u and v which we already know.
u is the direction to O before transformation.
v is the direction to O after transformation.
I want to know how to conduct the calculation and get the coordinate of Q
Thanks a lot.
Solution:
Rotation About an Arbitrary Axis in 3 Dimensions using the following matrix:
rotation axis vector (normalized): (u,v,w)
position coordinate of the rotation center: (a,b,c)
rotation angel: theta
Reference:
https://docs.google.com/viewer?a=v&pid=sites&srcid=ZGVmYXVsdGRvbWFpbnxnbGVubm11cnJheXxneDoyMTJiZTZlNzVlMjFiZTFi
for just single point no rotations is needed ... so knowns are:
u,v,O,P
so we now the distance is not changing:
|P-O| = |Q-O|
and directions are parallel to u,v so:
Q = O + v*(|P-O|/|v|)
But I suspect you want to construct rotation (transform matrix) such that more points (mesh perhaps) are transformed. If that is true then you need at least one known to get this right. Because there is infinite possible rotations transforming P -> Q but the rest of the mesh will be different for each ... so you need to know at least 2 non trivial points pair P0,P1 -> Q0,Q1 or axis of rotation or plane parallel to rotation or any other data known ...
Anyway in current state you can use as rotation axis vector perpendicular to u,v and angle obtained from dot product:
axis = cross (u,v)
ang = +/-acos(dot(u,v))
You just need to find out the sign of angle so try both and use the one for which the resultinq Q is where it should be so dot(Q-O,v) is max. To rotate around arbitrary axis and point use:
Rodrigues_rotation_formula
Also this might be helpfull:
Understanding 4x4 homogenous transform matrices
By computing dot product between v and u get the angle l between the vectors. Do a cross product of v and u (normalized) to produce axis of rotation vector a. Let w be a vector along vector u from O to P. To rotate point P into Q apply the following actions (in pseudo code) having axis a and angle l computed above:
float4 Rotate(float4 w, float l, float4 a)
{
float4x4 Mr = IDENTITY;
quat_t quat = IDENTITY;
float4 t = ZERO;
float xx, yy, zz, xy, xz, yz, wx, wy, wz;
quat[X] = a[X] * sin((-l / 2.0f));
quat[Y] = a[Y] * sin((-l / 2.0f));
quat[Z] = a[Z] * sin((-l / 2.0f));
quat[W] = cos((-l / 2.0f));
xx = quat[X] * quat[X];
yy = quat[Y] * quat[Y];
zz = quat[Z] * quat[Z];
xy = quat[X] * quat[Y];
xz = quat[X] * quat[Z];
yz = quat[Y] * quat[Z];
wx = quat[W] * quat[X];
wy = quat[W] * quat[Y];
wz = quat[W] * quat[Z];
Mr[0][0] = 1.0f - 2.0f * (yy + zz);
Mr[0][1] = 2.0f * (xy + wz);
Mr[0][2] = 2.0f * (xz - wy);
Mr[0][3] = 0.0f;
Mr[1][0] = 2.0f * (xy - wz);
Mr[1][1] = 1.0f - 2.0f * (xx + zz);
Mr[1][2] = 2.0f * (yz + wx);
Mr[1][3] = 0.0f;
Mr[2][0] = 2.0f * (xz + wy);
Mr[2][1] = 2.0f * (yz - wx);
Mr[2][2] = 1.0f - 2.0f * (xx + yy);
Mr[2][3] = 0.0f;
Mr[3][0] = 0.0f;
Mr[3][1] = 0.0f;
Mr[3][2] = 0.0f;
Mr[3][3] = 1.0f;
w = Mr * w;
return w;
}
Point Q is at the end of the rotated vector w. Algorithm used in the pseudo code is quaternion rotation.
If you know u, v, P, and O then I would suggest that you compute |OP| which should be preserved under rotations. Then multiply this length by the unit vector -v (I assumed u, v are unit vectors: if not - normalize them) and translate the origin by this -|OP|v vector. The negative sign in front of v comes from the description given in your question:"v is the direction to O after transformation".
P and Q are at the same distance R to O
R = sqrt( (x1-x0)^2 + (y1-y0)^2 + (z1-z0)^2 )
and OQ is collinear to v, so OQ = v * R / ||v|| where ||v|| is the norm of v
||v|| = sqrt( xv^2 + yv^2 + zv^2 )
So the coordinates of Q(xq,yq,zq) are:
xq= xo + xv * R / ||v||
yq= yo + yv * R / ||v||
zq= zo + zv * R / ||v||
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
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
How can I draw a perpendicular on a line segment from a given point? My line segment is defined as (x1, y1), (x2, y2), If I draw a perpendicular from a point (x3,y3) and it meets to line on point (x4,y4). I want to find out this (x4,y4).
I solved the equations for you:
k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / ((y2-y1)^2 + (x2-x1)^2)
x4 = x3 - k * (y2-y1)
y4 = y3 + k * (x2-x1)
Where ^2 means squared
From wiki:
In algebra, for any linear equation
y=mx + b, the perpendiculars will all
have a slope of (-1/m), the opposite
reciprocal of the original slope. It
is helpful to memorize the slogan "to
find the slope of the perpendicular
line, flip the fraction and change the
sign." Recall that any whole number a
is itself over one, and can be written
as (a/1)
To find the perpendicular of a given
line which also passes through a
particular point (x, y), solve the
equation y = (-1/m)x + b, substituting
in the known values of m, x, and y to
solve for b.
The slope of the line, m, through (x1, y1) and (x2, y2) is m = (y1 - y2) / (x1 - x2)
I agree with peter.murray.rust, vectors make the solution clearer:
// first convert line to normalized unit vector
double dx = x2 - x1;
double dy = y2 - y1;
double mag = sqrt(dx*dx + dy*dy);
dx /= mag;
dy /= mag;
// translate the point and get the dot product
double lambda = (dx * (x3 - x1)) + (dy * (y3 - y1));
x4 = (dx * lambda) + x1;
y4 = (dy * lambda) + y1;
You know both the point and the slope, so the equation for the new line is:
y-y3=m*(x-x3)
Since the line is perpendicular, the slope is the negative reciprocal. You now have two equations and can solve for their intersection.
y-y3=-(1/m)*(x-x3)
y-y1=m*(x-x1)
You will often find that using vectors makes the solution clearer...
Here is a routine from my own library:
public class Line2 {
Real2 from;
Real2 to;
Vector2 vector;
Vector2 unitVector = null;
public Real2 getNearestPointOnLine(Real2 point) {
unitVector = to.subtract(from).getUnitVector();
Vector2 lp = new Vector2(point.subtract(this.from));
double lambda = unitVector.dotProduct(lp);
Real2 vv = unitVector.multiplyBy(lambda);
return from.plus(vv);
}
}
You will have to implement Real2 (a point) and Vector2 and dotProduct() but these should be simple:
The code then looks something like:
Point2 p1 = new Point2(x1, y1);
Point2 p2 = new Point2(x2, y2);
Point2 p3 = new Point2(x3, y3);
Line2 line = new Line2(p1, p2);
Point2 p4 = getNearestPointOnLine(p3);
The library (org.xmlcml.euclid) is at:
http://sourceforge.net/projects/cml/
and there are unit tests which will exercise this method and show you how to use it.
#Test
public final void testGetNearestPointOnLine() {
Real2 p = l1112.getNearestPointOnLine(new Real2(0., 0.));
Real2Test.assertEquals("point", new Real2(0.4, -0.2), p, 0.0000001);
}
Compute the slope of the line joining points (x1,y1) and (x2,y2) as m=(y2-y1)/(x2-x1)
Equation of the line joining (x1,y1) and (x2,y2) using point-slope form of line equation, would be y-y2 = m(x-x2)
Slope of the line joining (x3,y3) and (x4,y4) would be -(1/m)
Again, equation of the line joining (x3,y3) and (x4,y4) using point-slope form of line equation, would be y-y3 = -(1/m)(x-x3)
Solve these two line equations as you solve a linear equation in two variables and the values of x and y you get would be your (x4,y4)
I hope this helps.
cheers
Find out the slopes for both the
lines, say slopes are m1 and m2 then
m1*m2=-1 is the condition for
perpendicularity.
Matlab function code for the following problem
function Pr=getSpPoint(Line,Point)
% getSpPoint(): find Perpendicular on a line segment from a given point
x1=Line(1,1);
y1=Line(1,2);
x2=Line(2,1);
y2=Line(2,1);
x3=Point(1,1);
y3=Point(1,2);
px = x2-x1;
py = y2-y1;
dAB = px*px + py*py;
u = ((x3 - x1) * px + (y3 - y1) * py) / dAB;
x = x1 + u * px;
y = y1 + u * py;
Pr=[x,y];
end
Mathematica introduced the function RegionNearest[] in version 10, 2014. This function could be used to return an answer to this question:
{x4,y4} = RegionNearest[Line[{{x1,y1},{x2,y2}}],{x3,y3}]
This is mostly a duplicate of Arnkrishn's answer. I just wanted to complete his section with a complete Mathematica code snippet:
m = (y2 - y1)/(x2 - x1)
eqn1 = y - y3 == -(1/m)*(x - x3)
eqn2 = y - y1 == m*(x - x1)
Solve[eqn1 && eqn2, {x, y}]
This is a C# implementation of the accepted answer. It's also using ArcGis to return a MapPoint as that's what we're using for this project.
private MapPoint GenerateLinePoint(double startPointX, double startPointY, double endPointX, double endPointY, double pointX, double pointY)
{
double k = ((endPointY - startPointY) * (pointX - startPointX) - (endPointX - startPointX) * (pointY - startPointY)) / (Math.Pow(endPointY - startPointY, 2)
+ Math.Pow(endPointX - startPointX, 2));
double resultX = pointX - k * (endPointY - startPointY);
double resultY = pointY + k * (endPointX - startPointX);
return new MapPoint(resultX, resultY, 0, SpatialReferences.Wgs84);
}
Thanks to Ray as this worked perfectly for me.
c#arcgis
Just for the sake of completeness, here is a solution using homogeneous coordinates.
The homogeneous points are:
p1 = (x1,y1,1), p2 = (x2,y2,1), p3 = (x3,y3,1)
a line through two points is their cross-product
l_12 := p1 x p2 = (y1-y2, x2-x1, x1*y2 - x2*y1)
The (signed) distance of a point to a line is their dot product.
d := l_12 * p3 = x3*(y1-y2) + y3*(x2-x1) + x1*y2 - x2*y1
The vector from p4 to p3 is d times the normal vector of l_12 divided by the squared length of the normal vector.
n2 := (y1-y2)^2 + (x2-x1)^2
p4 := p3 + d/n2*(y1-y2, x2-x1, 0)
Note: if you divide l_12 by the length of the normal vector
l_12 := l_12 / sqrt((y1-y2)^2 + (x2-x1)^2)
the distance d will be the euclidean distance.
First, calculate the linear function determined by the points
(x1,y2),(x2,y2).
We get:
y1 = mx+b1 where m and b1 are constants.
This step is easy to calculate by the formula of linear function between two points.
Then, calculate the linear function y that goes through (x3,y3).
The function slope is -m, where m is the slope of y1.
Then calculate the const b2 by the coordinates of the point (x3,y3).
We get y2 = -mx+b2 where m and b2 are constants.
The last thing to do is to find the intersection of y1, y2.
You can find x by solving the equation: -mx+b2 = mx+b1, then place x in one of the equations to find y.
This is a vectorized Matlab function for finding pairwise projections of m points onto n line segments. Here xp and yp are m by 1 vectors holding coordinates of m different points, and x1, y1, x2 and y2 are n by 1 vectors holding coordinates of start and end points of n different line segments.
It returns m by n matrices, x and y, where x(i, j) and y(i, j) are coordinates of projection of i-th point onto j-th line.
The actual work is done in first few lines and the rest of the function runs a self-test demo, just in case where it is called with no parameters. It's relatively fast, I managed to find projections of 2k points onto 2k line segments in less than 0.05s.
function [x, y] = projectPointLine(xp, yp, x1, y1, x2, y2)
if nargin > 0
xd = (x2-x1)';
yd = (y2-y1)';
dAB = xd.*xd + yd.*yd;
u = bsxfun(#rdivide, bsxfun(#times, bsxfun(#minus, xp, x1'), xd) + ...
bsxfun(#times, bsxfun(#minus, yp, y1'), yd), dAB);
x = bsxfun(#plus, x1', bsxfun(#times, u, xd));
y = bsxfun(#plus, y1', bsxfun(#times, u, yd));
else
nLine = 3;
nPoint = 2;
xp = rand(nPoint, 1) * 2 -1;
yp = rand(nPoint, 1) * 2 -1;
x1 = rand(nLine, 1) * 2 -1;
y1 = rand(nLine, 1) * 2 -1;
x2 = rand(nLine, 1) * 2 -1;
y2 = rand(nLine, 1) * 2 -1;
tic;
[x, y] = projectPointLine(xp, yp, x1, y1, x2, y2);
toc
close all;
plot([x1'; x2'], [y1'; y2'], '.-', 'linewidth', 2, 'markersize', 20);
axis equal;
hold on
C = lines(nPoint + nLine);
for i=1:nPoint
scatter(x(i, :), y(i, :), 100, C(i+nLine, :), 'x', 'linewidth', 2);
scatter(xp(i), yp(i), 100, C(i+nLine, :), 'x', 'linewidth', 2);
end
for i=1:nLine
scatter(x(:, i)', y(:, i)', 100, C(i, :), 'o', 'linewidth', 2);
end
end
end