451 votes

Distance la plus courte entre un point et un segment de ligne

J'ai besoin d'une fonction de base pour trouver la plus courte distance entre un point et un segment de ligne. N'hésitez pas à écrire la solution dans la langue que vous voulez, je peux le traduire dans ce que je suis en utilisant (Javascript).

EDIT: Mon segment de ligne est définie par deux points de terminaison. Donc, mon segment AB est définie par les deux points A (x1,y1) et B (x2,y2). J'essaie de trouver la distance entre ce segment de ligne et un point C (x3,y3). Mon géométrie compétences sont rouillées, de sorte que les exemples que j'ai vu sont à confusion, je suis désolé de l'avouer.

524voto

Grumdrig Points 6233

Eli, le code que vous avez installés sur est incorrect. Un point près de la ligne sur laquelle le segment se trouve, mais de loin l'une des extrémités du segment peut être mal jugé à proximité du segment. Mise à jour: La réponse incorrecte mentionné n'est plus accepté.

Voici quelques bon code en C++. Il suppose une classe de 2D vectoriel class vec2 {float x,y;}, essentiellement, avec des opérateurs pour ajouter, subract, échelle, etc, et à une distance et point en fonction du produit (c - x1 x2 + y1 y2).

float minimum_distance(vec2 v, vec2 w, vec2 p) {
  // Return minimum distance between line segment vw and point p
  const float l2 = length_squared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
  if (l2 == 0.0) return distance(p, v);   // v == w case
  // Consider the line extending the segment, parameterized as v + t (w - v).
  // We find projection of point p onto the line. 
  // It falls where t = [(p-v) . (w-v)] / |w-v|^2
  const float t = dot(p - v, w - v) / l2;
  if (t < 0.0) return distance(p, v);       // Beyond the 'v' end of the segment
  else if (t > 1.0) return distance(p, w);  // Beyond the 'w' end of the segment
  const vec2 projection = v + t * (w - v);  // Projection falls on the segment
  return distance(p, projection);
}

EDIT: j'avais besoin d'un Javascript de mise en œuvre, si elle est ici, sans dépendances (ou des commentaires, mais c'est un port direct de la ci-dessus). Les Points sont représentés comme des objets avec x et y attributs.

function sqr(x) { return x * x }
function dist2(v, w) { return sqr(v.x - w.x) + sqr(v.y - w.y) }
function distToSegmentSquared(p, v, w) {
  var l2 = dist2(v, w);
  if (l2 == 0) return dist2(p, v);
  var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
  if (t < 0) return dist2(p, v);
  if (t > 1) return dist2(p, w);
  return dist2(p, { x: v.x + t * (w.x - v.x),
                    y: v.y + t * (w.y - v.y) });
}
function distToSegment(p, v, w) { return Math.sqrt(distToSegmentSquared(p, v, w)); }

227voto

Joshua Points 1578

Voici le code complet plus simple en Javascript.

x, y est votre point de cible et x1, y1 à x2, y2 est votre segment de ligne.

Maj : Ajout (|| (x1 == x2 & & y1 = y2)) pour accueillir un segment de ligne avec une longueur de 0.

83voto

quano Points 5084

Il s’agit d’une implémentation de prévoir des SEGMENTS de ligne finie, lignes pas infinis comme la plupart des autres fonctions ici semblent être (c’est pourquoi j’ai fait cela).

Exemple est ici.

Python :

AS3 :

Celles-ci ont été faites de cette.

23voto

matti Points 1114

Dans ma propre question thread comment calculer la plus courte 2D distance entre un point et un segment de ligne dans tous les cas en C, C# / .NET 2.0 ou Java? On m'a demandé de mettre un C# réponse ici quand j'en trouve un: ici, c'est modifié à partir de http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Static :

//Compute the dot product AB . AC
private double DotProduct(double[] pointA, double[] pointB, double[] pointC)
{
    double[] AB = new double[2];
    double[] BC = new double[2];
    AB[0] = pointB[0] - pointA[0];
    AB[1] = pointB[1] - pointA[1];
    BC[0] = pointC[0] - pointB[0];
    BC[1] = pointC[1] - pointB[1];
    double dot = AB[0] * BC[0] + AB[1] * BC[1];

    return dot;
}

//Compute the cross product AB x AC
private double CrossProduct(double[] pointA, double[] pointB, double[] pointC)
{
    double[] AB = new double[2];
    double[] AC = new double[2];
    AB[0] = pointB[0] - pointA[0];
    AB[1] = pointB[1] - pointA[1];
    AC[0] = pointC[0] - pointA[0];
    AC[1] = pointC[1] - pointA[1];
    double cross = AB[0] * AC[1] - AB[1] * AC[0];

    return cross;
}

//Compute the distance from A to B
double Distance(double[] pointA, double[] pointB)
{
    double d1 = pointA[0] - pointB[0];
    double d2 = pointA[1] - pointB[1];

    return Math.Sqrt(d1 * d1 + d2 * d2);
}

//Compute the distance from AB to C
//if isSegment is true, AB is a segment, not a line.
double LineToPointDistance2D(double[] pointA, double[] pointB, double[] pointC, 
    bool isSegment)
{
    double dist = CrossProduct(pointA, pointB, pointC) / Distance(pointA, pointB);
    if (isSegment)
    {
        double dot1 = DotProduct(pointA, pointB, pointC);
        if (dot1 > 0) 
            return Distance(pointB, pointC);

        double dot2 = DotProduct(pointB, pointA, pointC);
        if (dot2 > 0) 
            return Distance(pointA, pointC);
    }
    return Math.Abs(dist);
} 

Je suis @SI ne pas répondre, mais de poser des questions donc j'espère que je ne reçois pas les millions de votes contre, pour certaines raisons, mais la construction de critique. Je voulais juste (et encouragé) à part de quelqu'un d'autre idées, car les solutions dans ce fil sont soit avec exotiques de la langue (Fortran, Mathematica) ou marqués comme défectueux par quelqu'un. La seule utile (par Grumdrig) pour moi, c'est écrit en C++ et personne n'a marqué défectueux. Mais il manque les méthodes (dot etc.) qui sont appelés.

21voto

Jon Harrop Points 26951

En F#, la distance entre le point d' c pour le segment de ligne entre a et b est donné par:

let pointToLineSegmentDistance (a: Vector, b: Vector) (c: Vector) =
  let d = b - a
  let s = d.Length
  let lambda = (c - a) * d / s
  let p = (lambda |> max 0.0 |> min s) * d
  (p - c).Length

Le vecteur d points de a de b le long du segment de ligne. Le produit scalaire de d/s avec c-a donne le paramètre du point de plus grande approche entre l'infini de la ligne et le point d' c. L' min et max fonction sont utilisées pour la fixation de ce paramètre pour la gamme 0..s , de sorte que le point se trouve entre a et b. Enfin, la longueur de l' p-c est la distance à partir de c de point le plus proche sur le segment de ligne.

Exemple d'utilisation:

pointToLineSegmentDistance (Vector(0.0, 0.0), Vector(1.0, 0.0)) (Vector(-1.0, 1.0))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X