2009-05-26 12 views

Respuesta

25

Necesita calculate the right angle distance en la línea. Luego debe definir qué es "cerrar" y probar si está dentro de esa distancia.

La ecuación que desea es:

d=|v^^·r|=(|(x_2-x_1)(y_1-y_0)-(x_1-x_0)(y_2-y_1)|)/(sqrt((x_2-x_1)^2+(y_2-y_1)^2)).

+9

Nota: Si se trata de segmentos de línea (es decir, líneas infinitamente largas), esto podría arrojar resultados erróneos: el punto podría estar lejos de los puntos finales del segmento y, sin embargo, tener una distancia normal pequeña ... – MartinStettner

+0

También tenga en cuenta que si va a dar la vuelta y comparar d a D, será más eficiente comparar | (x2 - x1) x (x1 - x0) |^2 a D^2 | x2 - x1 |^2, guardando dos raíces cuadradas y una división a costa de una multiplicación . – Dave

+0

Gracias Sr. Alan ¡Pero el enlace no funciona !. Probé la ecuación que pones antes, pero esto me da la distancia entre el nuevo punto y el primer punto de la línea, no la línea del agujero. Perdóneme por mi mal idioma. Sincerly, Wahid –

0

Básicamente, lo que quiere hacer es encontrar la línea normal, es decir, una línea perpendicular a su línea, que interseca su punto y la línea, y luego calcule la distancia a lo largo de esa línea.

+0

Sí, señor, pero estoy muy débil en matemáticas así que por favor ayúdenme y denme la ecuación para esto. –

+1

Ver el primero. Está todo allí. –

0

¿Qué tan cerca está el cercano?

Algunas geometrías le darán la respuesta que necesita, solo tiene que tener en cuenta los siguientes pasos.

Suponiendo que su me gusta es de la forma y = mx + b, la distancia más corta a su punto será la línea perpendicular a su línea de partida (m1 = -1/m), intersectando su punto en cuestión.

A partir de ahí se calcula la distancia entre el punto de intersección y el punto en cuestión.

+0

ligera corrección importante Ian, pendiente de la línea 2 es negativa recíproca de la línea de pendiente 1 (m1 = -1/m) - –

+0

Mi error ... Nunca es bueno para verificar mi trabajo :-) –

2

La respuesta de @Alan Jackson es casi perfecta, pero su primer comentario (y el más votada) sugiere que los puntos finales no se manejan correctamente. Para asegurarse de que el punto está en el segmento, simplemente cree un cuadro donde el segmento es una diagonal, luego verifique si el punto está dentro. Aquí está el pseudo-código:

línea dada AB, integrada por los puntos A y B, y el punto P, en la pregunta:

int buffer = 25;//this is the distance that you would still consider the point nearby 
Point topLeft = new Point(minimum(a.x, b.x), minimum(a.y, b.y)); 
Point bottomRight = new Point(maximum(a.x, b.x), maximum(a.y, b.y)); 
Rect box = new Rect(topLeft.x - buffer, topLeft.y - buffer, bottomRight.x + buffer, bottomRight.y + buffer); 
if (box.contains(p)) 
{ 
    //now run the test provided by Alan 
    if (test) 
     return true; 
} 
return false; 
+0

Gracias :) –

0

calcular el punto en la línea que está más cerca de ese punto .

Suponiendo que el segmento de línea es a y b, y el punto es p.

float vAPx = p.x - a.x; 
float vAPy = p.y - a.y; 
float vABx = b.x - a.x; 
float vABy = b.y - a.y; 
float sqDistanceAB = a.distanceSq(b); 
float ABAPproduct = vABx*vAPx + vABy*vAPy; 
float amount = ABAPproduct/sqDistanceAB; 
if (amount > 1) amount = 1; 
if (amount < 0) amount = 0; 

que le da 'cantidad', lo lejos a través del segmento de línea que está entre A y B (debidamente delimitada).

float nx = (amount * (b.x - a.x)) + a.x; 
    float ny = (amount * (b.y - a.y)) + a.y; 

Gives you point (nx, ny).

if (p.distance(nx,ny) > threshold) reject; 

Esto funcionará adecuadamente más allá del final del segmento de línea, ya que mantiene 'cantidad' entre 0 y 1.

Si no desea que un segmento de línea acotada librarse de los límites por cantidad. El resto del código seguirá funcionando, calculando las posiciones más allá y antes de A y más allá de B.

Hubo otra pregunta que afirmaba que esta pregunta era un duplicado pero, está pidiendo algo diferente, por lo tanto, mi solución resuelve la posición del punto y luego resuelve la distancia euclidiana (que en realidad resuelve ambas preguntas).

a.distanceSq (b) también se puede hacer como vABx vABx + vABy vABy, ya que ya lo hemos hecho.

0

Aquí hay una función de pitón que hace el truco. Debe funcionar en 2 o 3 dimensiones (o más) y maneja líneas verticales y horizontales sin casos especiales. Si establece clipToSegment en verdadero, el punto devuelto se recorta a los extremos si la línea proyectada se extiende más allá del segmento de línea suministrado.

def nearestPointOnLine(pt, r0, r1, clipToSegment = True): 
    r01 = r1 - r0   # vector from r0 to r1 
    d = np.linalg.norm(r01) # length of r01 
    r01u = r01/d   # unit vector from r0 to r1 
    r = pt - r0    # vector from r0 to pt 
    rid = np.dot(r, r01u) # projection (length) of r onto r01u 
    ri = r01u * rid   # projection vector 
    lpt = r0 + ri   # point on line 

    if clipToSegment:  # if projection is not on line segment 
     if rid > d:   # clip to endpoints if clipToSegment set 
      return r1 
     if rid < 0: 
      return r0 

    return lpt 

Uso: (distancia del punto [4,5] en el segmento de línea a partir de [2,4] a [4,6])

r0 = np.array([2,4]) 
r1 = np.array([4,6]) 
rpt = np.array([4,5]) 
pt = nearestPointOnLine(rpt, r0, r1, True) 

dist = np.linalg.norm(rpt-pt) 
print('dist', dist) 
Cuestiones relacionadas