¿Cómo puedo saber si un punto pertenece a cierta línea?

¿Cómo puedo saber si un punto pertenece a cierta línea?

Los ejemplos son apreciados, si es posible.

En la forma más simple, simplemente conecte las coordenadas en la ecuación de línea y verifique la igualdad.

Dado:

Point p (X=4, Y=5) Line l (Slope=1, YIntersect=1) 

Conecta X e Y:

  Y = Slope * X + YIntersect => 5 = 1 * 4 + 1 => 5 = 5 

Entonces sí, el punto está en juego.

Si sus líneas están representadas en forma (X1, Y1), (X2, Y2), entonces puede calcular la pendiente con:

  Slope = (y1 - y2) / (x1-x2) 

Y luego obtener el Y-Intersect con esto:

  YIntersect = - Slope * X1 + Y1; 

Editar: he arreglado el Y-Intersect (que ha sido X1 / Y1 …)

Deberá verificar que x1 - x2 no es 0 . Si es así, entonces verificar si el punto está en la línea es una simple cuestión de verificar si el valor Y en tu punto es igual a x1 o x2 . Además, verifique que la X del punto no sea ‘x1’ o ‘x2’.

Acabo de escribir una función que maneja algunos requisitos adicionales ya que uso esta verificación en una aplicación de dibujo:

  • Fuzziness: debe haber margen de error, ya que la función se usa para seleccionar líneas haciendo clic en ellas.
  • La línea tiene un EndPoint y un StartPoint, sin líneas infinitas.
  • Debe manejar líneas verticales y horizontales rectas, (x2 – x1) == 0 causa división por cero en las otras respuestas.
 private const double SELECTION_FUZZINESS = 3; internal override bool ContainsPoint(Point point) { LineGeometry lineGeo = geometry as LineGeometry; Point leftPoint; Point rightPoint; // Normalize start/end to left right to make the offset calc simpler. if (lineGeo.StartPoint.X < = lineGeo.EndPoint.X) { leftPoint = lineGeo.StartPoint; rightPoint = lineGeo.EndPoint; } else { leftPoint = lineGeo.EndPoint; rightPoint = lineGeo.StartPoint; } // If point is out of bounds, no need to do further checks. if (point.X + SELECTION_FUZZINESS < leftPoint.X || rightPoint.X < point.X - SELECTION_FUZZINESS) return false; else if (point.Y + SELECTION_FUZZINESS < Math.Min(leftPoint.Y, rightPoint.Y) || Math.Max(leftPoint.Y, rightPoint.Y) < point.Y - SELECTION_FUZZINESS) return false; double deltaX = rightPoint.X - leftPoint.X; double deltaY = rightPoint.Y - leftPoint.Y; // If the line is straight, the earlier boundary check is enough to determine that the point is on the line. // Also prevents division by zero exceptions. if (deltaX == 0 || deltaY == 0) return true; double slope = deltaY / deltaX; double offset = leftPoint.Y - leftPoint.X * slope; double calculatedY = point.X * slope + offset; // Check calculated Y matches the points Y coord with some easing. bool lineContains = point.Y - SELECTION_FUZZINESS <= calculatedY && calculatedY <= point.Y + SELECTION_FUZZINESS; return lineContains; } 

La mejor manera de determinar si un punto R = (rx, ry) se encuentra en la línea que conecta los puntos P = (px, py) y Q = (qx, qy) es comprobar si el determinante de la matriz

 {{qx - px, qy - py}, {rx - px, ry - py}}, 

a saber (qx – px) * (ry – py) – (qy – py) * (rx – px) está cerca de 0. Esta solución tiene varias ventajas relacionadas sobre las otras publicadas: primero, no requiere ningún caso especial para las líneas verticales En segundo lugar, no se divide (normalmente es una operación lenta). En tercer lugar, no desencadena un comportamiento de coma flotante malo cuando la línea es casi, pero no del todo vertical.

Creo que el Sr. Patrick McDonald puso la respuesta casi correcta y esta es la corrección de su respuesta:

 public bool IsOnLine(Point endPoint1, Point endPoint2, Point checkPoint) { return (((double)checkPoint.Y - endPoint1.Y)) / ((double)(checkPoint.X - endPoint1.X)) == ((double)(endPoint2.Y - endPoint1.Y)) / ((double)(endPoint2.X - endPoint1.X)); } 

y, por supuesto, hay muchas otras respuestas correctas, especialmente Mr.Josh, pero encontré que esta es la mejor.

Gracias por evryone.

Dado dos puntos en la línea L0 y L1 y el punto para probar P

  (L1 - L0) * (P - L0) n = (P - L0) - --------------------- (L1 - L0) (L1 - L0) * (L1 - L0) 

La norma del vector n es la distancia del punto P desde la línea a través de L0 y L1 . Si esta distancia es cero o lo suficientemente pequeña (en el caso de errores de redondeo), el punto se encuentra en la línea.

El símbolo * representa el producto escalar.

Ejemplo

 P = (5, 5) L0 = (0, 10) L1 = (20, -10) L1 - L0 = (20, -20) P - L0 = (5, -5) (20, -20) * (5, -5) n = (5, -5) - --------------------- (20, -20) (20, -20) * (20, -20) 200 = (5, -5) - --- (20, -20) 800 = (5, -5) - (5, -5) = (0, 0) 
 y = m * x + c 

Esta es la ecuación de una línea. xey son las coordenadas. Cada línea se caracteriza por su pendiente (m) y donde se cruza con el eje y (c).

Entonces, dados m & c para una línea, puedes determinar si el punto (x1, y1) está en la línea al verificar si la ecuación se cumple para x = x1 y y = y1

Si tiene una línea definida por sus puntos finales

 PointF pt1, pt2; 

y tienes un punto que quieres verificar

 PointF checkPoint; 

entonces podrías definir una función de la siguiente manera:

 bool IsOnLine(PointF endPoint1, PointF endPoint2, PointF checkPoint) { return (checkPoint.Y - endPoint1.Y) / (endPoint2.Y - endPoint1.Y) == (checkPoint.X - endPoint1.X) / (endPoint2.X - endPoint1.X); } 

y llámalo de la siguiente manera:

 if (IsOnLine(pt1, pt2, checkPoint) { // Is on line } 

Sin embargo, deberá verificar la división por cero.

Una línea 2D se representa generalmente usando una ecuación en dos variables x y y aquí es una ecuación bien conocida

y-y1 = (y1-y2) / (x1-x2) (x-x1)

Ahora imagine que su línea GDI + se extrae de (0,0) a (100, 100) y luego el valor de m = (0-100) / (0-100) = 1, por lo tanto, la ecuación para su línea es y-0 = 1 * (x-0) => y = x

Ahora que tenemos una ecuación para la línea en cuestión, es fácil de probar si un punto pertenece a esta línea. Un punto dado (x3, y3) pertenece a esta línea si satisface la ecuación de línea cuando sustituyes x = x3 ey = y3. Por ejemplo, el punto (10, 10) pertenece a esta línea ya que 10 = 10 pero (10,12) no pertenece a esta línea desde 12! = 10.

NOTA: Para una línea vertical, el valor de la pendiente (m) es infinito, pero para este caso especial puede usar la ecuación para una línea vertical directamente x = c donde c = x1 = x2.

Aunque debo decir que no estoy seguro de si esta es la forma más eficiente de hacerlo. Trataré de encontrar una forma más eficiente cuando tenga más tiempo disponible.

Espero que esto ayude.

La ecuación de la línea es:

 y = mx + c 

Entonces, un punto (a, b) está en esta línea si satisface esta ecuación, es decir, b = ma + c

¿Podría ser más específico?

¿De qué lenguaje de progtwigción estás hablando?

¿De qué entorno estás hablando?

¿De qué “líneas” estás hablando? ¿Texto? ¿Que punto? XY en la pantalla?

Como alternativa al método slope/y-intercept , elegí este enfoque usando Math.Atan2 :

 // as an extension method public static bool Intersects(this Vector2 v, LineSegment s) { // check from line segment start perspective var reference = Math.Atan2(s.Start.Y - s.End.Y, s.Start.X - s.End.X); var aTanTest = Math.Atan2(s.Start.Y - vY, s.Start.X - vX); // check from line segment end perspective if (reference == aTanTest) { reference = Math.Atan2(s.End.Y - s.Start.Y, s.End.X - s.Start.X); aTanTest = Math.Atan2(s.End.Y - vY, s.End.X - vX); } return reference == aTanTest; } 

La primera reference verificación determina el arcoTan desde el punto de inicio del segmento de línea hasta su punto final. Luego, desde la perspectiva del punto de inicio, determinamos el arcoTan al vector v .

Si esos valores son iguales, lo comprobamos desde la perspectiva del punto final.

Simple y maneja horizontal, vertical y todo lo demás en el medio.