2011-05-20 10 views
10

Tengo dos puntos A y B que definen un segmento de línea en la pantalla de un dispositivo más otro punto C. Usando algoritmo corto y eficiente que es fácil de codificar biblioteca), ¿cómo puedo verificar si el segmento de línea AB está dentro de una distancia R desde C?Comprobando un segmento de línea está dentro de una distancia desde un punto

Sé que hay una manera simple de encontrar la distancia más corta desde un punto a una línea, pero supone que la línea es infinitamente larga. Lo que tengo es un segmento de línea con dos puntos finales.

Consideré publicar esto en Math SE pero decidí no hacerlo ya que no quiero obtener toda esa fórmula matemática larga como la respuesta como en https://math.stackexchange.com/questions/2837/how-to-tell-if-a-line-segment-intersects-with-a-circle. Lo que necesito es un algoritmo informático eficiente y legible, no un teorema matemático formal.

p/s: Tengo el siguiente Objective-C método esqueleto que necesita ser implementada:

typedef struct { 
    CGPoint a; 
    CGPoint b; 
} CGLineSegment; 

+ (BOOL)isLineSegment:(CGLineSegment)line withinRadius:(CGFloat)radius fromPoint:(CGPoint)point { 

} 

EDITAR CON SOLUCIÓN:

gracias a la Respuesta de veredesmarald (que ya he aceptado) he implementado el método, poner aquí como referencia para otras personas:

+ (BOOL)isLineSegment:(CGLineSegment)line withinRadius:(CGFloat)radius fromPoint:(CGPoint)point { 
    CGPoint v = CGPointMake(line.b.x - line.a.x, line.b.y - line.a.y); 
    CGPoint w = CGPointMake(point.x - line.a.x, point.y - line.a.y); 
    CGFloat c1 = dotProduct(w, v); 
    CGFloat c2 = dotProduct(v, v); 
    CGFloat d; 
    if (c1 <= 0) { 
     d = distance(point, line.a); 
    } 
    else if (c2 <= c1) { 
     d = distance(point, line.b); 
    } 
    else { 
     CGFloat b = c1/c2; 
     CGPoint Pb = CGPointMake(line.a.x + b * v.x, line.a.y + b * v.y); 
     d = distance(point, Pb); 
    } 
    return d <= radius; 
} 

CGFloat distance(const CGPoint p1, const CGPoint p2) { 
    return sqrt(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2)); 
} 

CGFloat dotProduct(const CGPoint p1, const CGPoint p2) { 
    return p1.x * p2.x + p1.y * p2.y; 
} 
+0

Antes de poder traducirlo a código, debe tener (¡y preferiblemente entender!) Las matemáticas involucradas. –

+0

@Bart Kiers yup eso es cierto, pero entonces estoy buscando la matemática, no la fórmula, como he enfatizado en mi pregunta. No tengo problemas con la matemática de geometría simple a intermedia. – Lukman

Respuesta

7

Cuando tenía que poner en práctica una reunieron hod para determinar la distancia de un punto a un intervalo para una asignación de gráficos, encontré esta página muy informativo: About Lines and Distance of a Point to a Line

En particular, la sección distancia de un punto a un Rayo o segmento debería ser de interés para usted .

Pseudocódigo del artículo de (donde · es producto de punto y d() es la distancia entre dos puntos):

distance(Point P, Segment P0:P1) 
{ 
     v = P1 - P0 
     w = P - P0 
     if ((c1 = w·v) <= 0) 
      return d(P, P0) 
     if ((c2 = v·v) <= c1) 
      return d(P, P1) 
     b = c1/c2 
     Pb = P0 + bv 
     return d(P, Pb) 
} 

Este método se basa en el producto escalar para determinar si la base de la perpendicular está dentro del intervalo, y si no es que punto final está más cerca.

+0

Es curioso cómo esta implementación del algoritmo descrito en la otra respuesta no parece ser solo eso ;-) +1 porque es correcto. – danyowdee

+0

¡funciona! ¡Gracias! He agregado mi implementación objetivo-c en la pregunta como referencia para los demás :) – Lukman

Cuestiones relacionadas