2012-01-21 15 views
5

En el plano 2D, tengo un punto y una línea. ¿Cómo conseguir el punto de espejo a lo largo de esta línea?¿Cómo calcular el punto de espejo a lo largo de una línea?

+0

Creo que este es el sitio equivocado para esa pregunta, ya que no trata directamente con la programación. Hay otro sitio para eso: http://math.stackexchange.com/ –

+0

¿Cómo se define su línea? (Supongo que su punto está definido con sus coordenadas x, y). La línea – biziclop

+0

se define utilizando dos puntos o usando 1 punto y 1 vector. –

Respuesta

5

Supongamos que la ecuación de la línea es ax + by + c = 0. Ahora imagina una línea perpendicular a ella, que se puede representar por -bx + ay + d = 0 (el producto de las pendientes de dos líneas perpendiculares es -1). Ahora el problema es encontrar d. Coloque la coordenada del punto en la segunda línea, y obtendrá el valor de d fácilmente.

La segunda parte es, para encontrar un punto en la segunda línea que es equidistante como el primer punto de la primera línea. Para eso, puedes encontrar la intersección de las dos líneas. Calcule las diferencias en x y y del punto dado y el punto de intersección. Ahora agréguelos al valor x y y del punto de intersección. Eso le da el punto que necesita (puede necesitar negar las diferencias, eso depende del orden de resta que use).

+0

Undid my down vote –

2

Calcule el punto más cercano de la línea al punto en cuestión. Luego invierte la dirección del vector entre esos puntos y agrégalo al punto más cercano de la línea. Voilà, has encontrado el punto de espejo.

+0

¿Cómo obtener el punto más cercano a la línea? –

+0

Con matemáticas: http: // paulbourke.net/geometry/pointline/o prueba google: http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=find+closest+point+on+line+from+another+point – Anteru

15

Cuando cosas así se hacen en los programas de computadora, uno de los problemas que puede tener que tratar es realizar estos cálculos usando aritmética entera solamente (o tanto como sea posible), asumiendo que la entrada está en enteros. Hacer esto en números enteros tanto como sea posible es un tema aparte que no abordaré aquí.

La siguiente es una solución "matemática", que si se implementa literalmente requerirá cálculos de coma flotante. No sé si esto es aceptable en tu caso. Puede optimizarlo a su gusto usted mismo.

(1) representar a su línea L por

A * x + B * y + C = 0 

ecuación. Tenga en cuenta que el vector (A, B) es el vector normal de esta línea.

Por ejemplo, si la línea se define por dos puntos X1(x1, y1) y X2(x2, y2), luego

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

(2) Normalizar la ecuación dividiendo todos los coeficientes por la longitud del vector (A, B). Es decir. calcular la longitud

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

y luego calcular los valores

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

La ecuación

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

es todavía una ecuación equivalente de su línea L excepto que ahora el vector normal (A', B') es una unidad vector.

(3) Tome su punto P(px, py) y calcular el valor

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

Esto le dará la firmado distancia D desde su punto P a su línea L. En otras palabras, esta es la distancia desde P hasta el punto más cercano en L (realmente no nos importa el punto más cercano, solo necesitamos la distancia).

El signo dice que lado de la línea L se encuentra el punto P. Si P se encuentra en el mismo lado al que apunta el vector (A', B') (lado "positivo"), la distancia es positiva. Si P se encuentra en el otro lado (lado "negativo"), la distancia es negativa.

(4) el fin de encontrar su punto de espejo P'(px', py') tiene que mover su punto de P por la distancia absoluta |2 * D| través de la línea L al otro lado.

"Al otro lado de la línea" en realidad significa que si el punto P yacía en el lado "positivo" de L, entonces tenemos que moverlo en contra de la dirección del vector (A', B') hacia el lado "negativo". Y viceversa, si el punto P estaba en el lado "negativo" de L, entonces tenemos que moverlo en el sentido del vector (A', B') al lado "positivo".

Esto se puede expresar simplemente moviendo el punto la distancia de -2 * D (observe el signo menos) en la dirección del vector (A', B').

Eso significa que

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

le da su punto de P'(px', py') espejo.


Como alternativa, puede utilizar un enfoque basado en encontrar el punto más cercano N real en la línea L y luego lo que refleja su punto de P con relación a N. Esto ya se sugiere en otras respuestas, solo describiré cómo lo haría.

(1) Construir una ecuación

A*x + B*y + C = 0 

para su línea L exactamente como se describe en el paso 1 anterior. No hay necesidad de normalizar esta ecuación.

(2) Crea una ecuación para la línea perpendicular que pasa por P.Digamos que la línea perpendicular está representado por

D*x + E*y + F = 0 

Los D y E coeficientes son conocidos de inmediato

D = B 
E = -A 

mientras F se puede calcular mediante la sustitución de punto P en la ecuación

F = -D*px - E*py 

(3) Encuentra la intersección de estos dos líneas resolviendo el sistema de dos ecuaciones lineales

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

Cramer's rule funciona muy bien en este caso. La fórmula dada en el artículo Line intersection en Wikipedia no es más que una aplicación de la regla de Cramer a este sistema.

La solución le da el punto más cercano N(nx, ny) que estábamos buscando.

(4) Ahora acaba de calcular

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

para encontrar su punto de P'(px', py').

Tenga en cuenta que este enfoque se puede implementar casi por completo en enteros. El único paso que puede perder precisión es la división dentro de la regla de Cramer en el paso 3. Por supuesto, como siempre, el precio que tendrá que pagar por la solución "casi integral" es la necesidad de aritmética de gran número. Incluso los coeficientes C y F pueden desbordarse, sin siquiera mencionar los cálculos dentro de las fórmulas de reglas de Cramer.

+2

MUCHA mejor respuesta de programación que la marca marcada en mi opinión. – badweasel

+0

Estoy de acuerdo con @badweasel. Este debería ser marcado como la respuesta correcta. – xfx

1

I se supone que tiene la ubicación de la punta, y una ecuación para la línea, es decir,

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

primer lugar, el caso obvio donde a = 0 (es decir, línea paralela al eje x) produce

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

para el caso más general,

  1. Obtener la ecuación genérica para una línea ortogonal a la suya: y = cx + d , Con ac = -1

    ==> c = -1/a

  2. Determinar b de modo que P pertenece a la línea ortogonal: y1 = -X1/a + d

    ==> d = y1 + x1/a

  3. Obtener la intersección entre las dos líneas: y = -x/a + y1 + x1/a = ax + b

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

  4. Obtenga el vector entre la intersección y su punto P, agréguelo al punto de intersección para obtener el punto de espejo P '.

    ==> P '(x2, y2), con x2 = x1 + 2 ((y1 + x1/a -b)/(a ​​+ 1/a) - x1) y2 = y1 + 2 (un (x1 + y1/a-b)/(a ​​+ 1/a) + b - y1)

Algunos pasos pueden simplificarse, pero esta es la idea general. Hice el álgebra mientras escribía, por lo que podría haber errores. Si encuentras uno, por favor dejame saber.

+0

Esto no va a funcionar para una línea vertical ('x = constante') y va a tener problemas para líneas casi verticales. Debe comenzar con una ecuación implícita ('ax + by + c = 0'). –

+0

@TedHopp: Correcto, esta solución no es lo suficientemente general. – Karolos

1

He hecho exactamente esto para otro sistema que he construido .. Hay mucho más que esto en mi código; así que espero haber extraído todos los bits necesarios ... Line.ClosestPoint(Point pt) es el método que desea ...

El algoritmo se basa en la idea de que la pendiente de una línea perpindicular a cualquier línea dada es el recíproco multiplicativo negativo de la pendiente de la línea dada. es decir, si una línea tiene una pendiente m, entonces la otra línea tiene una pendiente -1/m. Entonces, todo lo que tiene que hacer es formar una línea a través del punto con pendiente igual a -1/my encontrar la intersección de esta línea con la línea original.

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

Los detalles dependen de cómo se representa su línea. Si representa como un punto arbitrario P en la línea junto con un vector columna unidad n a lo largo de la línea, entonces el punto de espejo Q 'a cualquier punto Q está dada por:

Q '= Q + 2 (I - nnT) (P - Q)

(Aquí, I es la matriz identidad 2x2, nT es la transpuesta de n (tratamiento de n como una matriz de 2x1), y nnT es el 2x2 matriz formada por la multiplicación de matrices estándar de n con nT.) no es muy difícil demostrar que Q 'no cambiará si se mueve P en cualquier lugar de la línea.

No es difícil convertir otras representaciones de líneas en una representación de vector de punto/unidad.

Cuestiones relacionadas