In 2D plane, I have a point and a line. How to get the mirror point along this line?
I have done exactly this for another system I have built.. There's a lot more than this in my code; so I hope I have extracted all the necessary bits... Line.ClosestPoint(Point pt)
is the method you want...
The algorithm is based on the idea that the slope of a line perpindicular to any given line is the negative multiplicative reciprocal of the slope of the given line. i.e., if one line has slope m, then the other line has slope -1/m. So all you need to do is form a line through the point with slope equal to -1/m and find the intersection of this line with the original line.
public class Line
{
protected const double epsilon = 1.0e-8;
public Point Anchor { get; set; }
public double Slope { get; set; }
public virtual Point ClosestPoint(Point pt)
{ return Intersection(Make(pt, -1 / Slope)); }
protected Line(Point anchor, double slope)
{
Anchor = anchor;
Slope = slope;
}
public static Line Make(Point anchor, double slope)
{ return new Line(anchor, slope); }
public virtual Point Intersection(Line line)
{
if (lib.Within(line.Slope, Slope, epsilon))
if( lib.Within(line.YIntcpt, YIntcpt, epsilon))
// code for NoInterceptException not included
throw new NoInterceptException(
"The two lines overlap.");
else return Point.NullPoint;
// ----------------------------------------
double tm = Slope, om = line.Slope,
tx = Anchor.X, ty = Anchor.Y,
ox = line.Anchor.X, oy = line.Anchor.Y;
var x = double.IsInfinity(tm) ? tx :
double.IsInfinity(om) ? ox :
(tm * tx - om * ox + oy - ty) /
(tm - om);
var y = double.IsInfinity(tm) ?
om * (x - ox) + oy :
tm * (x - tx) + ty;
return Point.Make(x, y);
}
}
public struct Point
{
const double epsilon = 1.0e-12;
private readonly bool isDef;
private readonly double y;
private readonly double x;
public bool HasValue { get { return isDef; } }
public bool IsNull { get { return !isDef; } }
private Point(double xValue, double yValue)
{ x = xValue; y = yValue; isDef = true; }
public static Point Make(double x, double y)
{ return new Point(x, y); }
public double X
{
get
{
// code for AlgebraicException not included
if (IsNull) throw new AlgebraicException("Null Point Object");
return x;
}
}
public double Y
{
get
{
// code for AlgebraicException not included
if (IsNull) throw new AlgebraicException("Null Point Object");
return y;
}
}
public static Point NullPoint { get { return new Point();}}
// Other functionality
}
The details depend on how your line is represented. If you represent it as an arbitrary point P on the line together with a unit column vector n along the line, then the mirror point Q' to any point Q is given by:
Q' = Q + 2(I - nnT)(P - Q)
(Here, I is the 2x2 identity matrix, nT is the transpose of n (treating n as a 2x1 matrix), and nnT is the 2x2 matrix formed by standard matrix multiplication of n with nT.) It's not too hard to show that Q' will not change if you move P anywhere on the line.
It's not hard to convert other line representations into a point/unit vector representation.
I develop JS code which calculate formula from Ted Hop answer : Q' = Q + 2(I - nnT)(P - Q) transformed to
Q' = Q + 2(I - d2vvT)(P - Q)
Where column vector v=R-P is normal to line but not unit (like n) where P and R are two arbitrary line points; the vvT is outer product; the d=1/sqrt(vx*vx + vy*vy)
is inverse length of v. Because we use d2 (=r in code) we can optimize calculations by omit sqrt
// 2D Points P=[x,y] and R are points on line,
// Q is point for which we want to find reflection
function mirror(Q,[P,R]) {
let [vx,vy]= [ R[0]-P[0], R[1]-P[1] ];
let [x,y] = [ P[0]-Q[0], P[1]-Q[1] ];
let r= 1/(vx*vx+vy*vy);
return [ Q[0] +2*(x -x*vx*vx*r -y*vx*vy*r),
Q[1] +2*(y -y*vy*vy*r -x*vx*vy*r) ];
}
console.log( mirror([3,2], [[2,4],[4,5]]) )
Compute the closest point on the line to the point in question. Then invert the direction of the vector between those points and add it to the closest point on the line. Voilà, you have found the mirror point.
I assume you have the location of the point, and an equation for your line, i.e.
P=(x1,y1) and y = ax + b
First, the obvious case where a=0 (i.e. line parallel to the x axis) yields
P'(x2,y2), with x2 = x1, y2 = y1 + 2(b-y1)
For the more general case,
Get the generic equation for a line orthogonal to yours: y = cx + d, with ac = -1
==> c = -1/a
Determine b so that P belongs to the orthogonal line: y1 = -x1/a + d
==> d = y1 + x1/a
Get the intersection between the two lines: y = -x/a + y1 + x1/a = ax + b
==> x = (y1 + x1/a -b)/(a+1/a), y = a(y1 + x1/a -b)/(a+1/a) + b
Get the vector between the intersection and your point P, add that to the intersection point to obtain the mirror point P'.
==> P'(x2,y2), with x2 = x1 + 2((y1 + x1/a -b)/(a+1/a) - x1) y2 = y1 + 2(a(y1 + x1/a -b)/(a+1/a) + b - y1)
Some steps can be simplified but this is the general idea. I did the algebra while typing, so there could be mistakes. If you find one, please let me know.
Suppose the equation of the line is ax + by + c = 0
. Now imagine a line perpendicular to it, which can be represented by -bx + ay + d = 0
(product of slopes of two perpendicular lines is -1). Now the problem is to find d
. Put the co-ordinate of the point on the second line, and you'll get the value of d
easily.
The second part is, to find a point on the second line which is equidistant as the first point from the first line. For that, you can find the intersection of the two lines. Calculate the differences in x
and y
of the given point and the intersection point. Now add those to the x
and y
value of the intersecting point. That gives the point you need (you may need to negate the differences - that's up to the order of subtraction you use).