2012-01-21 3 views
5

В 2D-плоскости у меня есть точка и линия. Как получить зеркальную точку вдоль этой линии?Как вычислить точку зеркала вдоль линии?

+0

Я считаю, что это неправильный сайт для этого вопроса, так как он не имеет прямого отношения к программированию. Для этого есть другой сайт: http://math.stackexchange.com/ –

+0

Как определяется ваша строка? (Я предполагаю, что ваша точка определена с ее координатами x, y.) – biziclop

+0

строка определяется с использованием двух точек или с использованием 1 точки и 1 вектора. –

ответ

5

Предположим, что уравнение линии равно ax + by + c = 0. Теперь представьте себе перпендикулярную ему линию, которая может быть представлена ​​-bx + ay + d = 0 (произведение наклонов двух перпендикулярных линий равно -1). Теперь стоит найти d. Поместите координату точки во вторую строку, и вы легко получите значение d.

Вторая часть - найти точку на второй линии, которая равноудалена как первая точка первой линии. Для этого вы можете найти пересечение двух линий. Рассчитайте разницу в x и y данной точки и точку пересечения. Теперь добавьте их в значение x и значение y точки пересечения. Это дает вам необходимую точку (вам, возможно, придется отрицать различия - это зависит от порядка вычитания, который вы используете).

+0

Undid my down vote –

2

Вычислить ближайшую точку на линии до рассматриваемой точки. Затем инвертируйте направление вектора между этими точками и добавьте его в ближайшую точку на линии. Войла, ты нашел зеркальную точку.

+0

Как получить ближайшую точку к линии? –

+0

С математикой: http: // paulbourke.net/geometry/pointline/или попробуйте google: http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=find+closest+point+on+line+from+another+point – Anteru

15

Когда такие вещи выполняются в компьютерных программах, одной из проблем, с которыми вам придется иметь дело, является выполнение этих вычислений с использованием только целочисленной арифметики (или, насколько это возможно), если входной сигнал находится в целых числах. Выполнение этого в целых числах как можно больше - это отдельная проблема, которую я не буду здесь описывать.

Следующее - это «математическое» решение, которое, если оно будет реализовано буквально, потребует вычисления с плавающей запятой. Я не знаю, приемлемо ли это в вашем случае. Вы можете сами оптимизировать его на свой вкус.

(1) Представлять свою линию L по

A * x + B * y + C = 0 

уравнения. Обратите внимание, что вектор (A, B) является нормальным вектором этой линии.

Например, если линия определяется двумя точками X1(x1, y1) и X2(x2, y2), затем

A = y2 - y1 
B = -(x2 - x1) 
C = -A * x1 - B * y1 

(2) Нормализация уравнение путем деления всех коэффициентов на длину вектора (A, B). То есть вычислить длину

M = sqrt(A * A + B * B) 

, а затем вычислить значения

A' = A/M 
B' = B/M 
C' = C/M 

Уравнение

A' * x + B' * y + C' = 0 

по-прежнему эквивалентное уравнение вашей линии L за исключением того, что теперь вектор нормали (A', B') является единицей вектор.

(3) Возьмите точку P(px, py) и вычислить значение

D = A' * px + B' * py + C' 

Это даст вам подписал расстояние D с вашей точки P к вашей линии L. Другими словами, это расстояние от P до ближайшей точки на L (нам на самом деле не важно, какая ближайшая точка, нам просто нужно расстояние).

Знак говорит, что сторона линии L точка P лежит на. Если P лежит на той же стороне, то вектор (A', B') указывает на («положительная» сторона), расстояние положительное. Если P находится на другой стороне («отрицательная» сторона), расстояние отрицательное.

(4) Для того, чтобы найти свою точку зеркала P'(px', py') вам нужно переместить точку P абсолютного расстоянием |2 * D| через линию L на другую сторону.

«Через линию» на самом деле означает, что если точка P лежит на «положительной» стороне L, то мы должны двигаться против направления вектора (A', B') к «отрицательной» стороне. И наоборот, если точка P лежала на «отрицательной» стороне L, тогда мы должны перенести ее в направлении вектора (A', B') на «положительную» сторону.

Это можно просто выразить как перемещение точки на расстоянии -2 * D (обратите внимание минус) в направлении вектора (A', B').

Это означает, что

px' = px - 2 * A' * D 
py' = py - 2 * B' * D 

дает Вам зеркало точку P'(px', py').


В качестве альтернативы, вы можете использовать подход, основанный на поиске фактической ближайшей точки N на линии L, а затем отражает вашу точку P по отношению к N. Это уже предложено в других ответах, я просто опишу, как я это сделаю.

(1) Построить уравнение

A*x + B*y + C = 0 

для линии L точно так, как описано в пункте 1 выше. Нет необходимости нормализовать это уравнение.

(2) Построить уравнение для перпендикулярной линии, которая проходит через P.Допустим, что перпендикулярная линия представлена ​​

D*x + E*y + F = 0 

Коэффициенты D и E известны сразу

D = B 
E = -A 

в то время как F можно вычислить путем подстановки точки P в уравнение

F = -D*px - E*py 

(3) Найти перекресток этих две линии путем решения системы двух линейных уравнений

A*x + B*y = -C 
D*x + E*y = -F 

Cramer's rule работает очень хорошо в этом случае. Формула, приведенная в статье Line intersection в Википедии, является не чем иным, как применением правила Крамера к этой системе.

Решение дает вам ближайшую точку N(nx, ny), которую мы ищем.

(4) Теперь просто вычислить

px' = nx + (nx - px) 
py' = ny + (ny - py) 

найти свою точку P'(px', py').

Обратите внимание, что этот подход может быть почти полностью реализован в целых числах. Единственным шагом, который может потерять точность, является разделение внутри правила Крамера на шаге 3. Конечно, как обычно, цена, которую вам придется заплатить за «почти интегральное» решение, - это необходимость в арифметике большого числа. Даже коэффициенты C и F могут переполняться, даже не упоминая вычисления в формулах правил Крамера.

+2

МНОГОКРАТНО программируемый ответ, чем чек, отмеченный на мой взгляд. – badweasel

+0

Я согласен с @badweasel. Этот должен быть отмечен как правильный ответ. – xfx

1

Я предполагаю, что у вас есть местоположение точки, и уравнение для вашей линии, т.е.

P=(x1,y1) and y = ax + b 

Во-первых, очевидно, случай, когда а = 0 (т.е. линия, параллельная оси х) дает

P'(x2,y2), with x2 = x1, y2 = y1 + 2(b-y1) 

в более общем случае,

  1. Получить общую формулу для линии, ортогональной к твоему: у = сх + d С ас = -1

    ==> с = -1/а

  2. Определить б так, что Р принадлежит ортогональной линии: y1 = -x1/а + г

    ==> d = у1 + х1/д

  3. Получить пересечение между двумя линиями: Y = -x/A + y1 + x1/а = ах + Ь

    ==> х = (у1 + x1/a -b)/(a ​​+ 1/a), y = a (y1 + x1/a -b)/(a ​​+ 1/a) + b

  4. Получите вектор между пересечением и точкой P, добавьте это в точку пересечения, чтобы получить зеркальную точку P '.

    ==> Р '(х2, у2), с x2 = x1 + 2 ((x1 + y1/а) -b/(а + 1/а) - x1) у2 = у1 + 2 (а (у1 + х1/а -b)/(а + 1/а) + б - у1)

Некоторые шаги могут быть упрощены, но это общая идея. Я делал алгебру при наборе текста, поэтому могут быть ошибки. Если вы его найдете, сообщите мне.

+0

Это не будет работать для вертикальной линии ('x = constant'), и это будет иметь проблемы для почти вертикальных линий. Вам нужно начать с неявного уравнения ('ax + by + c = 0'). –

+0

@TedHopp: Правильно, это решение недостаточно общего. – Karolos

1

Я сделал именно это для другой системы, которую я построил. В моем коде есть намного больше. поэтому я надеюсь, что я извлек все необходимые биты ... Line.ClosestPoint(Point pt) - это метод, который вы хотите ...

Алгоритм основан на идее, что наклон линии, перпендикулярной любой данной линии, является отрицательным мультипликативным обратным наклон данной линии. то есть, если одна линия имеет наклон m, то другая линия имеет наклон -1/m. Итак, все, что вам нужно сделать, это сформировать линию через точку с наклоном, равным -1/м, и найти пересечение этой линии с исходной строкой.

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 

} 
6

Детали зависят от того, как представлена ​​ваша линия. Если представить его в виде произвольной точки P на линии вместе с вектором единицы столбца п вдоль линии, то точка зеркала Q 'в любой точке Q определяется по формуле:

Q '= Q + 2 (я - ппТ) (Р - Q)

(Здесь я единичная матрица 2x2, пТ является транспонированная п (лечения п в качестве матрицы 2x1), и ппТ является 2х2 матрица, составленная из стандартного матричного умножения п с пТ.) Это не слишком сложно, чтобы показать, что Q 'не изменится, если вы двигаетесь P в любом месте на линии.

Нетрудно преобразовать другие представления линий в представление вектора/единицы вектора.

Смежные вопросы