Come posso sapere se un punto appartiene a una determinata linea?

Come posso sapere se un punto appartiene a una determinata linea?

Gli esempi sono apprezzati, se ansible.

Nella forma più semplice, inserisci le coordinate nell’equazione della riga e controlla l’uguaglianza.

Dato:

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

Collega X e Y:

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

Quindi sì, il punto è sulla linea.

Se le linee sono rappresentate in forma (X1, Y1), (X2, Y2), allora puoi calcolare la pendenza con:

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

E poi prendi l’intersezione Y con questo:

  YIntersect = - Slope * X1 + Y1; 

Modifica: ho corretto Y-Intersect (che è stato X1 / Y1 …)

Dovrai controllare che x1 - x2 non sia 0 . Se lo è, quindi verificare se il punto è sulla linea è una semplice questione di controllare se il valore Y nel tuo punto è uguale a x1 o x2 . Inoltre, controlla che la X del punto non sia ‘x1’ o ‘x2’.

Ho appena scritto una funzione che gestisce alcuni requisiti aggiuntivi poiché utilizzo questo controllo in un’applicazione di disegno:

  • Sfocatura – Ci deve essere spazio per errori poiché la funzione viene utilizzata per selezionare le linee facendo clic su di esse.
  • La linea ha ottenuto un endpoint e un punto di partenza, senza linee infinite.
  • Deve gestire linee verticali e orizzontali diritte, (x2 – x1) == 0 causa la divisione per zero nelle altre risposte.
 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; } 

Il modo migliore per determinare se un punto R = (rx, ry) si trova sulla linea che collega i punti P = (px, py) e Q = (qx, qy) è per verificare se il determinante della matrice

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

vale a dire (qx – px) * (ry – py) – (qy – py) * (rx – px) è vicino a 0. Questa soluzione ha molti vantaggi rispetto agli altri postati: in primo luogo, non richiede alcun caso particolare per le linee verticali , in secondo luogo, non divide (di solito un’operazione lenta), terzo, non innesca un cattivo comportamento a virgola mobile quando la linea è quasi, ma non del tutto verticale.

Penso che Mr.Patrick McDonald abbia messo la risposta quasi corretta e questa è la correzione della sua risposta:

 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)); } 

e naturalmente ci sono molte altre risposte corrette, specialmente Mr.Josh, ma ho trovato che questo è il migliore.

Grazie per evryone.

Dati due punti sulla linea L0 e L1 e il punto per testare P

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

La norma del vettore n è la distanza del punto P dalla linea attraverso L0 e L1 . Se questa distanza è zero o abbastanza piccola (nel caso di errori di arrotondamento), il punto si trova sulla linea.

Il simbolo * rappresenta il prodotto punto.

Esempio

 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 

Questa è l’equazione di una linea. x & y sono le coordinate. Ogni linea è caratterizzata dalla sua inclinazione (m) e dal punto in cui interseca l’asse y (c).

Quindi, dato il valore di m & c per una riga, puoi determinare se il punto (x1, y1) si trova sulla linea controllando se l’equazione vale per x = x1 ey = y1

Se hai una linea definita dai suoi endpoint

 PointF pt1, pt2; 

e tu hai un punto che vuoi controllare

 PointF checkPoint; 

allora potresti definire una funzione come segue:

 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); } 

e chiamalo come segue:

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

Tuttavia dovrai controllare la divisione per zero.

Una linea 2D è generalmente rappresentata utilizzando un’equazione in due variabili xey qui è un’equazione ben nota

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

Ora immagina che la tua linea GDI + sia disegnata da (0,0) a (100, 100) quindi il valore di m = (0-100) / (0-100) = 1 quindi l’equazione per la tua linea è y-0 = 1 * (x-0) => y = x

Ora che abbiamo un’equazione per la linea in questione, è facile verificare se un punto appartiene a questa linea. Un punto dato (x3, y3) appartiene a questa linea se soddisfa l’equazione di riga quando si sostituisce x = x3 ey = y3. Ad esempio il punto (10, 10) appartiene a questa linea poiché 10 = 10 ma (10,12) non appartiene a questa riga dal 12! = 10.

NOTA: per una linea verticale il valore della pendenza (m) è infinito ma per questo caso speciale è ansible utilizzare l’equazione per una linea verticale direttamente x = c dove c = x1 = x2.

Anche se devo dire che non sono sicuro se questo è il modo più efficace per farlo. Cercherò di trovare un modo più efficiente quando avrò ancora un po ‘di tempo a disposizione.

Spero che questo ti aiuti.

L’equazione della linea è:

 y = mx + c 

Quindi un punto (a, b) si trova su questa linea se soddisfa questa equazione cioè b = ma + c

Potresti essere più specifico?

Di che linguaggio di programmazione stai parlando?

Di quale ambiente stai parlando?

Di quali “linee” stai parlando? Testo? Che punto? XY sullo schermo?

In alternativa al metodo slope/y-intercept , ho scelto questo approccio 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; } 

Il primo reference verifica determina l’arcTan dal punto iniziale del segmento di linea al suo punto finale. Quindi dalla prospettiva del punto di partenza, determiniamo l’arcTan al vettore v .

Se tali valori sono uguali, controlliamo dal punto di vista del punto finale.

Semplice e gestisce orizzontale, verticale e tutto il resto.